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

com.microsoft.windowsazure.services.blob.client.CloudBlobContainer Maven / Gradle / Ivy

There is a newer version: 0.4.6
Show newest version
/**
 * Copyright 2011 Microsoft Corporation
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.microsoft.windowsazure.services.blob.client;

import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.InvalidKeyException;
import java.util.Calendar;
import java.util.Date;
import java.util.EnumSet;
import java.util.HashMap;

import javax.xml.stream.XMLStreamException;

import com.microsoft.windowsazure.services.core.storage.Constants;
import com.microsoft.windowsazure.services.core.storage.DoesServiceRequest;
import com.microsoft.windowsazure.services.core.storage.OperationContext;
import com.microsoft.windowsazure.services.core.storage.ResultContinuation;
import com.microsoft.windowsazure.services.core.storage.ResultContinuationType;
import com.microsoft.windowsazure.services.core.storage.ResultSegment;
import com.microsoft.windowsazure.services.core.storage.StorageCredentialsSharedAccessSignature;
import com.microsoft.windowsazure.services.core.storage.StorageErrorCodeStrings;
import com.microsoft.windowsazure.services.core.storage.StorageException;
import com.microsoft.windowsazure.services.core.storage.StorageExtendedErrorInformation;
import com.microsoft.windowsazure.services.core.storage.utils.PathUtility;
import com.microsoft.windowsazure.services.core.storage.utils.UriQueryBuilder;
import com.microsoft.windowsazure.services.core.storage.utils.Utility;
import com.microsoft.windowsazure.services.core.storage.utils.implementation.ExecutionEngine;
import com.microsoft.windowsazure.services.core.storage.utils.implementation.LazySegmentedIterator;
import com.microsoft.windowsazure.services.core.storage.utils.implementation.SegmentedStorageOperation;
import com.microsoft.windowsazure.services.core.storage.utils.implementation.StorageOperation;

/**
 * Represents a container in the Windows Azure Blob service.
 * 

* Containers hold directories, which are encapsulated as {@link CloudBlobDirectory} objects, and directories hold block * blobs and page blobs. Directories can also contain sub-directories. */ public final class CloudBlobContainer { /** * Converts the ACL string to a BlobContainerPermissions object. * * @param aclString * the string to convert. * @return The resulting BlobContainerPermissions object. */ static BlobContainerPermissions getContainerAcl(final String aclString) { BlobContainerPublicAccessType accessType = BlobContainerPublicAccessType.OFF; if (!Utility.isNullOrEmpty(aclString)) { final String lowerAclString = aclString.toLowerCase(); if ("container".equals(lowerAclString)) { accessType = BlobContainerPublicAccessType.CONTAINER; } else if ("blob".equals(lowerAclString)) { accessType = BlobContainerPublicAccessType.BLOB; } else { throw new IllegalArgumentException(String.format( "Invalid acl public access type returned '%s'. Expected blob or container.", aclString)); } } final BlobContainerPermissions retVal = new BlobContainerPermissions(); retVal.setPublicAccess(accessType); return retVal; } /** * Represents the container metadata. */ protected HashMap metadata; /** * Holds the container properties. */ BlobContainerProperties properties; /** * Holds the name of the container. */ String name; /** * Holds the URI of the container. */ URI uri; /** * Holds a reference to the associated service client. */ private CloudBlobClient blobServiceClient; /** * Initializes a new instance of the CloudBlobContainer class. * * @param client * the reference to the associated service client. */ private CloudBlobContainer(final CloudBlobClient client) { this.metadata = new HashMap(); this.properties = new BlobContainerProperties(); this.blobServiceClient = client; } /** * Creates an instance of the CloudBlobContainer class using the specified address and client. * * @param containerAddress * A String that represents either the absolute URI to the container, or the container name. * @param client * A {@link CloudBlobClient} object that represents the associated service client, and that specifies the * endpoint for the Blob service. * * @throws StorageException * If a storage service error occurred. * @throws URISyntaxException * If the resource URI is invalid. */ public CloudBlobContainer(final String containerAddress, final CloudBlobClient client) throws URISyntaxException, StorageException { this(client); final URI resURI = PathUtility.appendPathToUri(client.getEndpoint(), containerAddress); this.uri = resURI; this.name = PathUtility.getContainerNameFromUri(resURI, client.isUsePathStyleUris()); this.parseQueryAndVerify(this.uri, client, client.isUsePathStyleUris()); } /** * Creates an instance of the CloudBlobContainer class using the specified URI and client. * * @param uri * A java.net.URI object that represents the URI of the container. * @param client * A {@link CloudBlobClient} object that represents the associated service client, and that specifies the * endpoint for the Blob service. * * @throws StorageException * If a storage service error occurred. * @throws URISyntaxException * If the resource URI is invalid. */ public CloudBlobContainer(final URI uri, final CloudBlobClient client) throws URISyntaxException, StorageException { this(client); this.uri = uri; this.name = PathUtility.getContainerNameFromUri(uri, client.isUsePathStyleUris()); this.parseQueryAndVerify(this.uri, client, client.isUsePathStyleUris()); } /** * Creates the container. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public void create() throws StorageException { this.create(null, null); } /** * Creates the container using the specified options and operation context. * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public void create(BlobRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); final StorageOperation impl = new StorageOperation( options) { @Override public Void execute(final CloudBlobClient client, final CloudBlobContainer container, final OperationContext opContext) throws Exception { final HttpURLConnection request = ContainerRequest.create(container.uri, this.getRequestOptions() .getTimeoutIntervalInMs(), opContext); ContainerRequest.addMetadata(request, container.metadata, opContext); client.getCredentials().signRequest(request, 0L); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { this.setNonExceptionedRetryableFailure(true); return null; } // Set attributes final BlobContainerAttributes attributes = ContainerResponse.getAttributes(request, client.isUsePathStyleUris()); container.properties = attributes.getProperties(); container.name = attributes.getName(); return null; } }; ExecutionEngine .executeWithRetry(this.blobServiceClient, this, impl, options.getRetryPolicyFactory(), opContext); } /** * Creates the container if it does not exist. * * @return true if the container did not already exist and was created; otherwise, false. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public boolean createIfNotExist() throws StorageException { return this.createIfNotExist(null, null); } /** * Creates the container if it does not exist, using the specified request options and operation context. * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @return true if the container did not already exist and was created; otherwise, false. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public boolean createIfNotExist(BlobRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); final StorageOperation impl = new StorageOperation( options) { @Override public Boolean execute(final CloudBlobClient client, final CloudBlobContainer container, final OperationContext opContext) throws Exception { final HttpURLConnection request = ContainerRequest.create(container.uri, this.getRequestOptions() .getTimeoutIntervalInMs(), opContext); ContainerRequest.addMetadata(request, container.metadata, opContext); client.getCredentials().signRequest(request, 0L); this.setResult(ExecutionEngine.processRequest(request, opContext)); // Validate response code here if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_CREATED) { // Set attributes final BlobContainerAttributes attributes = ContainerResponse.getAttributes(request, client.isUsePathStyleUris()); container.properties = attributes.getProperties(); container.name = attributes.getName(); return true; } else if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_CONFLICT) { final StorageException potentialConflictException = StorageException.translateException(request, null, opContext); StorageExtendedErrorInformation extendedInfo = potentialConflictException .getExtendedErrorInformation(); if (extendedInfo == null) { // If we cant validate the error then the error must be surfaced to the user. throw potentialConflictException; } if (!extendedInfo.getErrorCode().equals(StorageErrorCodeStrings.CONTAINER_ALREADY_EXISTS)) { this.setException(potentialConflictException); this.setNonExceptionedRetryableFailure(true); // return false instead of null to avoid SCA issues return false; } return false; } else { throw StorageException.translateException(request, null, opContext); } } }; return ExecutionEngine.executeWithRetry(this.blobServiceClient, this, impl, options.getRetryPolicyFactory(), opContext); } /** * Deletes the container. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public void delete() throws StorageException { this.delete(null, null); } /** * Deletes the container using the specified request options and operation context. * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public void delete(BlobRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); final StorageOperation impl = new StorageOperation( options) { @Override public Void execute(final CloudBlobClient client, final CloudBlobContainer container, final OperationContext opContext) throws Exception { final HttpURLConnection request = ContainerRequest.delete(container.uri, this.getRequestOptions() .getTimeoutIntervalInMs(), opContext); client.getCredentials().signRequest(request, -1L); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_ACCEPTED) { this.setNonExceptionedRetryableFailure(true); } return null; } }; ExecutionEngine .executeWithRetry(this.blobServiceClient, this, impl, options.getRetryPolicyFactory(), opContext); } /** * Deletes the container if it exists. * * @return true if the container did not already exist and was created; otherwise, false. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public boolean deleteIfExists() throws StorageException { return this.deleteIfExists(null, null); } /** * Deletes the container if it exists using the specified request options and operation context. * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @return true if the container did not already exist and was created; otherwise, false. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public boolean deleteIfExists(BlobRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); final StorageOperation impl = new StorageOperation( options) { @Override public Boolean execute(final CloudBlobClient client, final CloudBlobContainer container, final OperationContext opContext) throws Exception { final HttpURLConnection request = ContainerRequest.delete(container.uri, this.getRequestOptions() .getTimeoutIntervalInMs(), opContext); client.getCredentials().signRequest(request, -1L); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_ACCEPTED) { container.updatePropertiesFromResponse(request); return true; } else if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) { return false; } else { this.setNonExceptionedRetryableFailure(true); // return false instead of null to avoid SCA issues return false; } } }; return ExecutionEngine.executeWithRetry(this.blobServiceClient, this, impl, options.getRetryPolicyFactory(), opContext); } /** * Downloads the container's attributes, which consist of metadata and properties. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public void downloadAttributes() throws StorageException { this.downloadAttributes(null, null); } /** * Downloads the container's attributes, which consist of metadata and properties, using the specified request * options and operation context. * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public void downloadAttributes(BlobRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); final StorageOperation impl = new StorageOperation( options) { @Override public Void execute(final CloudBlobClient client, final CloudBlobContainer container, final OperationContext opContext) throws Exception { final HttpURLConnection request = ContainerRequest.getProperties(container.uri, this .getRequestOptions().getTimeoutIntervalInMs(), opContext); client.getCredentials().signRequest(request, -1L); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); return null; } // Set attributes final BlobContainerAttributes attributes = ContainerResponse.getAttributes(request, client.isUsePathStyleUris()); container.metadata = attributes.getMetadata(); container.properties = attributes.getProperties(); container.name = attributes.getName(); return null; } }; ExecutionEngine .executeWithRetry(this.blobServiceClient, this, impl, options.getRetryPolicyFactory(), opContext); } /** * Downloads the permission settings for the container. * * @return A {@link BlobContainerPermissions} object that represents the container's permissions. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public BlobContainerPermissions downloadPermissions() throws StorageException { return this.downloadPermissions(null, null); } /** * Downloads the permissions settings for the container using the specified request options and operation context. * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @return A {@link BlobContainerPermissions} object that represents the container's permissions. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public BlobContainerPermissions downloadPermissions(BlobRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); final StorageOperation impl = new StorageOperation( options) { @Override public BlobContainerPermissions execute(final CloudBlobClient client, final CloudBlobContainer container, final OperationContext opContext) throws Exception { final HttpURLConnection request = ContainerRequest.getAcl(container.uri, this.getRequestOptions() .getTimeoutIntervalInMs(), opContext); client.getCredentials().signRequest(request, -1L); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); } container.updatePropertiesFromResponse(request); final String aclString = ContainerResponse.getAcl(request); final BlobContainerPermissions containerAcl = getContainerAcl(aclString); final AccessPolicyResponse response = new AccessPolicyResponse(request.getInputStream()); for (final String key : response.getAccessIdentifiers().keySet()) { containerAcl.getSharedAccessPolicies().put(key, response.getAccessIdentifiers().get(key)); } return containerAcl; } }; return ExecutionEngine.executeWithRetry(this.blobServiceClient, this, impl, options.getRetryPolicyFactory(), opContext); } /** * Returns a value that indicates whether the container exists. * * @return true if the container exists, otherwise false. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public boolean exists() throws StorageException { return this.exists(null, null); } /** * Returns a value that indicates whether the container exists, using the specified request options and operation * context. * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @return true if the container exists, otherwise false. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public boolean exists(BlobRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); final StorageOperation impl = new StorageOperation( options) { @Override public Boolean execute(final CloudBlobClient client, final CloudBlobContainer container, final OperationContext opContext) throws Exception { final HttpURLConnection request = ContainerRequest.getProperties(container.uri, this .getRequestOptions().getTimeoutIntervalInMs(), opContext); client.getCredentials().signRequest(request, -1L); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_OK) { container.updatePropertiesFromResponse(request); return Boolean.valueOf(true); } else if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) { return Boolean.valueOf(false); } else { this.setNonExceptionedRetryableFailure(true); // return false instead of null to avoid SCA issues return false; } } }; return ExecutionEngine.executeWithRetry(this.blobServiceClient, this, impl, options.getRetryPolicyFactory(), opContext); } /** * Returns a shared access signature for the blob using the specified shared access policy. Note this does not * contain the leading "?". *

* A shared access signature is a token that provides delegated access to blob resources. You can provide this token * to clients in order to grant them specific permissions to resources for a controlled period of time. A shared * access signature created for a blob grants access just to the content and metadata of that blob. A shared access * signature created for a container grants access to the content and metadata of any blob in the container, and to * the list of blobs in the container. *

* The parameters of the shared access signature that govern access are: *

    *
  • The start time at which the signature becomes valid.
  • *
  • The time at which it expires.
  • *
  • The permissions that it grants.
  • *
* These parameters are specified in an access policy, represented by the {@link SharedAccessPolicy} class. There * are two ways to specify an access policy: *
    *
  • * You can specify it on a single shared access signature. In this case, the interval over which the signature may * be valid is limited to one hour.
  • *
  • * You can specify it by creating a container-level access policy, which can be associated with one or more shared * access signatures. This approach has the advantage of making it possible to revoke a shared access signature, if * it should be compromised. To specify that the access policy should be used by the signature, call an overload * that includes the groupPolicyIdentifier parameter.
  • *
* You can also specify some parameters of the access policy on the signature and some on a container-level access * policy. However, if you specify a parameter in both places, the parameter specified for the signature overrides * that provided by the container-level access policy. For more information on shared access signatures, see Creating a Shared Access Signature. For * details on container-level access policies, see Specifying a Container-Level Access Policy. * * @param policy * A SharedAccessPolicy object that represents the access policy for the shared access * signature. * * @return A String that represents the shared access signature. * * @throws IllegalArgumentException * If the credentials are invalid or the blob is a snapshot. * @throws InvalidKeyException * If the credentials are invalid. * @throws StorageException * If a storage service error occurred. */ public String generateSharedAccessSignature(final SharedAccessPolicy policy) throws InvalidKeyException, StorageException { return this.generateSharedAccessSignature(policy, null); } /** * Returns a shared access signature for the blob using the shared access policy and operation context. Note this * does not contain the leading "?". *

* A shared access signature is a token that provides delegated access to blob resources. You can provide this token * to clients in order to grant them specific permissions to resources for a controlled period of time. A shared * access signature created for a blob grants access just to the content and metadata of that blob. A shared access * signature created for a container grants access to the content and metadata of any blob in the container, and to * the list of blobs in the container. *

* The parameters of the shared access signature that govern access are: *

    *
  • The start time at which the signature becomes valid.
  • *
  • The time at which it expires.
  • *
  • The permissions that it grants.
  • *
* These parameters are specified in an access policy, represented by the {@link SharedAccessPolicy} class. There * are two ways to specify an access policy: *
    *
  • * You can specify it on a single shared access signature. In this case, the interval over which the signature may * be valid is limited to one hour.
  • *
  • * You can specify it by creating a container-level access policy, which can be associated with one or more shared * access signatures. This approach has the advantage of making it possible to revoke a shared access signature, if * it should be compromised. To specify that the access policy should be used by the signature, call an overload * that includes the groupPolicyIdentifier parameter.
  • *
* You can also specify some parameters of the access policy on the signature and some on a container-level access * policy. However, if you specify a parameter in both places, the parameter specified for the signature overrides * that provided by the container-level access policy. For more information on shared access signatures, see Creating a Shared Access Signature. For * details on container-level access policies, see Specifying a Container-Level Access Policy. * * @param policy * A SharedAccessPolicy object that represents the access policy for the shared access * signature. * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @return A String that represents the shared access signature. * * @throws IllegalArgumentException * If the credentials are invalid or the blob is a snapshot. * @throws InvalidKeyException * If the credentials are invalid. * @throws StorageException * If a storage service error occurred. */ public String generateSharedAccessSignature(final SharedAccessPolicy policy, OperationContext opContext) throws InvalidKeyException, StorageException { if (opContext == null) { opContext = new OperationContext(); } return this.generateSharedAccessSignatureCore(policy, null, opContext); } /** * Returns a shared access signature for the blob using the specified group policy identifier. Note this does not * contain the leading "?". *

* A shared access signature is a token that provides delegated access to blob resources. You can provide this token * to clients in order to grant them specific permissions to resources for a controlled period of time. A shared * access signature created for a blob grants access just to the content and metadata of that blob. A shared access * signature created for a container grants access to the content and metadata of any blob in the container, and to * the list of blobs in the container. *

* The parameters of the shared access signature that govern access are: *

    *
  • The start time at which the signature becomes valid.
  • *
  • The time at which it expires.
  • *
  • The permissions that it grants.
  • *
* These parameters are specified in an access policy, represented by the {@link SharedAccessPolicy} class. There * are two ways to specify an access policy: *
    *
  • * You can specify it on a single shared access signature. In this case, the interval over which the signature may * be valid is limited to one hour.
  • *
  • * You can specify it by creating a container-level access policy, which can be associated with one or more shared * access signatures. This approach has the advantage of making it possible to revoke a shared access signature, if * it should be compromised. To specify that the access policy should be used by the signature, call an overload * that includes the groupPolicyIdentifier parameter.
  • *
* You can also specify some parameters of the access policy on the signature and some on a container-level access * policy. However, if you specify a parameter in both places, the parameter specified for the signature overrides * that provided by the container-level access policy. For more information on shared access signatures, see Creating a Shared Access Signature. For * details on container-level access policies, see Specifying a Container-Level Access Policy. * * @param groupPolicyIdentifier * A String that represents the container-level access policy. * * @return A String that represents the shared access signature. * * @throws IllegalArgumentException * If the credentials are invalid or the blob is a snapshot. * @throws InvalidKeyException * If the credentials are invalid. * @throws StorageException * If a storage service error occurred. */ public String generateSharedAccessSignature(final String groupPolicyIdentifier) throws InvalidKeyException, StorageException { return this.generateSharedAccessSignature(groupPolicyIdentifier, null); } /** * Returns a shared access signature for the blob using the specified group policy identifier and operation context. * Note this does not contain the leading "?". *

* A shared access signature is a token that provides delegated access to blob resources. You can provide this token * to clients in order to grant them specific permissions to resources for a controlled period of time. A shared * access signature created for a blob grants access just to the content and metadata of that blob. A shared access * signature created for a container grants access to the content and metadata of any blob in the container, and to * the list of blobs in the container. *

* The parameters of the shared access signature that govern access are: *

    *
  • The start time at which the signature becomes valid.
  • *
  • The time at which it expires.
  • *
  • The permissions that it grants.
  • *
* These parameters are specified in an access policy, represented by the {@link SharedAccessPolicy} class. There * are two ways to specify an access policy: *
    *
  • * You can specify it on a single shared access signature. In this case, the interval over which the signature may * be valid is limited to one hour.
  • *
  • * You can specify it by creating a container-level access policy, which can be associated with one or more shared * access signatures. This approach has the advantage of making it possible to revoke a shared access signature, if * it should be compromised. To specify that the access policy should be used by the signature, call an overload * that includes the groupPolicyIdentifier parameter.
  • *
* You can also specify some parameters of the access policy on the signature and some on a container-level access * policy. However, if you specify a parameter in both places, the parameter specified for the signature overrides * that provided by the container-level access policy. For more information on shared access signatures, see Creating a Shared Access Signature. For * details on container-level access policies, see Specifying a Container-Level Access Policy. * * @param groupPolicyIdentifier * A String that represents the container-level access policy. * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @return A String that represents the shared access signature. * * @throws IllegalArgumentException * If the credentials are invalid or the blob is a snapshot. * @throws InvalidKeyException * If the credentials are invalid. * @throws StorageException * If a storage service error occurred. */ public String generateSharedAccessSignature(final String groupPolicyIdentifier, OperationContext opContext) throws InvalidKeyException, StorageException { if (opContext == null) { opContext = new OperationContext(); } return this.generateSharedAccessSignatureCore(null, groupPolicyIdentifier, opContext); } /** * Returns a shared access signature for the container. Note this does not contain the leading "?". * * @param policy * The access policy for the shared access signature. * @param groupPolicyIdentifier * A container-level access policy. * @return a shared access signature for the container. * @throws InvalidKeyException * @throws StorageException * @throws IllegalArgumentException */ private String generateSharedAccessSignatureCore(final SharedAccessPolicy policy, final String groupPolicyIdentifier, OperationContext opContext) throws InvalidKeyException, StorageException { if (opContext == null) { opContext = new OperationContext(); } if (!this.blobServiceClient.getCredentials().canCredentialsSignRequest()) { final String errorMessage = "Cannot create Shared Access Signature unless the Account Key credentials are used by the BlobServiceClient."; throw new IllegalArgumentException(errorMessage); } final String resourceName = this.getSharedAccessCanonicalName(); final String signature = SharedAccessSignatureHelper.generateSharedAccessSignatureHash(policy, groupPolicyIdentifier, resourceName, this.blobServiceClient, opContext); final UriQueryBuilder builder = SharedAccessSignatureHelper.generateSharedAccessSignature(policy, groupPolicyIdentifier, "c", signature); return builder.toString(); } /** * Returns a reference to a {@link CloudBlockBlob} object that represents a block blob in this container. * * @param blobAddressUri * A String that represents the name of the blob, or the absolute URI to the blob. * * @return A {@link CloudBlockBlob} object that represents a reference to the specified block blob. * * @throws StorageException * If a storage service error occurred. * @throws URISyntaxException * If the resource URI is invalid. */ public CloudBlockBlob getBlockBlobReference(final String blobAddressUri) throws URISyntaxException, StorageException { Utility.assertNotNullOrEmpty("blobAddressUri", blobAddressUri); final URI address = PathUtility.appendPathToUri(this.uri, blobAddressUri); return new CloudBlockBlob(address, this.blobServiceClient, this); } /** * Returns a reference to a {@link CloudBlockBlob} object that represents a block blob in this container, using the * specified snapshot ID. * * @param blobAddressUri * A String that represents the name of the blob, or the absolute URI to the blob. * @param snapshotID * A String that represents the snapshot ID of the blob. * * @return A {@link CloudBlockBlob} object that represents a reference to the specified block blob. * * @throws StorageException * If a storage service error occurred. * @throws URISyntaxException * If the resource URI is invalid. */ public CloudBlockBlob getBlockBlobReference(final String blobAddressUri, final String snapshotID) throws URISyntaxException, StorageException { Utility.assertNotNullOrEmpty("blobAddressUri", blobAddressUri); final URI address = PathUtility.appendPathToUri(this.uri, blobAddressUri); final CloudBlockBlob retBlob = new CloudBlockBlob(address, snapshotID, this.blobServiceClient); retBlob.setContainer(this); return retBlob; } /** * Returns a reference to a {@link CloudBlobDirectory} object that represents a virtual blob directory within this * container. * * @param relativeAddress * A String that represents the name of the virtual blob directory, or the absolute URI to * the virtual blob directory. * * @return A {@link CloudBlobDirectory} that represents a virtual blob directory within this container. * * @throws StorageException * If a storage service error occurred. * @throws URISyntaxException * If the resource URI is invalid. */ public CloudBlobDirectory getDirectoryReference(final String relativeAddress) throws URISyntaxException, StorageException { Utility.assertNotNullOrEmpty("relativeAddress", relativeAddress); final URI address = PathUtility.appendPathToUri(this.uri, relativeAddress); return new CloudBlobDirectory(address, null, this.blobServiceClient); } /** * Returns the metadata for the container. * * @return A java.util.HashMap object that represents the metadata for the container. */ public HashMap getMetadata() { return this.metadata; } /** * Returns the name of the container. * * @return A String that represents the name of the container. */ public String getName() { return this.name; } /** * Returns a reference to a {@link CloudPageBlob} object that represents a page blob in this container. * * @param blobAddressUri * A String that represents the name of the blob, or the absolute URI to the blob. * * @return A {@link CloudPageBlob} object that represents a reference to the specified page blob. * * @throws StorageException * If a storage service error occurred. * @throws URISyntaxException * If the resource URI is invalid. */ public CloudPageBlob getPageBlobReference(final String blobAddressUri) throws URISyntaxException, StorageException { Utility.assertNotNullOrEmpty("blobAddressUri", blobAddressUri); final URI address = PathUtility.appendPathToUri(this.uri, blobAddressUri); return new CloudPageBlob(address, this.blobServiceClient, this); } /** * Returns a reference to a {@link CloudPageBlob} object that represents a page blob in the directory, using the * specified snapshot ID. * * @param blobAddressUri * A String that represents the name of the blob, or the absolute URI to the blob. * @param snapshotID * A String that represents the snapshot ID of the blob. * * @return A {@link CloudPageBlob} object that represents a reference to the specified page blob. * * @throws StorageException * If a storage service error occurred. * @throws URISyntaxException * If the resource URI is invalid. */ public CloudPageBlob getPageBlobReference(final String blobAddressUri, final String snapshotID) throws URISyntaxException, StorageException { Utility.assertNotNullOrEmpty("blobAddressUri", blobAddressUri); final URI address = PathUtility.appendPathToUri(this.uri, blobAddressUri); final CloudPageBlob retBlob = new CloudPageBlob(address, snapshotID, this.blobServiceClient); retBlob.setContainer(this); return retBlob; } /** * Returns the properties for the container. * * @return A {@link BlobContainerProperties} object that represents the properties for the container. */ public BlobContainerProperties getProperties() { return this.properties; } /** * Returns the Blob service client associated with this container. * * @return A {@link CloudBlobClient} object that represents the service client associated with this container. */ public CloudBlobClient getServiceClient() { return this.blobServiceClient; } /** * Returns the canonical name for shared access. * * @return the canonical name for shared access. */ private String getSharedAccessCanonicalName() { if (this.blobServiceClient.isUsePathStyleUris()) { return this.getUri().getPath(); } else { return PathUtility.getCanonicalPathFromCredentials(this.blobServiceClient.getCredentials(), this.getUri() .getPath()); } } /** * Returns the URI after applying the authentication transformation. * * @return A java.net.URI object that represents the URI after applying the authentication * transformation. * * @throws IllegalArgumentException * If an unexpected value is passed. * @throws StorageException * If a storage service error occurred. * @throws URISyntaxException * If the resource URI is invalid. */ protected URI getTransformedAddress() throws URISyntaxException, StorageException { if (this.blobServiceClient.getCredentials().doCredentialsNeedTransformUri()) { if (this.uri.isAbsolute()) { return this.blobServiceClient.getCredentials().transformUri(this.uri); } else { final StorageException ex = Utility.generateNewUnexpectedStorageException(null); ex.getExtendedErrorInformation().setErrorMessage("Blob Object relative URIs not supported."); throw ex; } } else { return this.uri; } } /** * Returns the URI for this container. * * @return The absolute URI to the container. */ public URI getUri() { return this.uri; } /** * Returns an enumerable collection of blob items for the container. * * @return An enumerable collection of {@link ListBlobItem} objects that represents the items in this container. */ @DoesServiceRequest public Iterable listBlobs() { return this.listBlobs(null, false, EnumSet.noneOf(BlobListingDetails.class), null, null); } /** * Returns an enumerable collection of blob items for the container whose names begin with the specified prefix. * * @param prefix * A String that represents the blob name prefix. This value must be preceded either by the * name of the container or by the absolute path to the container. * * @return An enumerable collection of {@link ListBlobItem} objects that represents the items whose names begin with * the specified prefix in this container. */ @DoesServiceRequest public Iterable listBlobs(final String prefix) { return this.listBlobs(prefix, false, EnumSet.noneOf(BlobListingDetails.class), null, null); } /** * Returns an enumerable collection of blob items whose names begin with the specified prefix, using the specified * flat or hierarchical option, listing details options, request options, and operation context. * * @param prefix * A String that represents the blob name prefix. This value must be preceded either by the * name of the container or by the absolute path to the container. * @param useFlatBlobListing * true to indicate that the returned list will be flat; false to indicate that * the returned list will be hierarchical. * @param listingDetails * A java.util.EnumSet object that contains {@link BlobListingDetails} values that indicate * whether snapshots, metadata, and/or uncommitted blocks are returned. Committed blocks are always * returned. * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @return An enumerable collection of {@link ListBlobItem} objects that represent the block items whose names begin * with the specified prefix in this directory. * * @throws StorageException * If a storage service error occurred. * @throws URISyntaxException * If the resource URI is invalid. */ @DoesServiceRequest public Iterable listBlobs(final String prefix, final boolean useFlatBlobListing, final EnumSet listingDetails, BlobRequestOptions options, OperationContext opContext) { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); if (!useFlatBlobListing && listingDetails != null && listingDetails.contains(BlobListingDetails.SNAPSHOTS)) { throw new IllegalArgumentException( "Listing snapshots is only supported in flat mode (no delimiter). Consider setting useFlatBlobListing to true."); } final SegmentedStorageOperation> impl = new SegmentedStorageOperation>( options, null) { @Override public ResultSegment execute(final CloudBlobClient client, final CloudBlobContainer container, final OperationContext opContext) throws Exception { final ResultSegment result = CloudBlobContainer.this.listBlobsCore(prefix, useFlatBlobListing, listingDetails, -1, this.getToken(), (BlobRequestOptions) this.getRequestOptions(), this, opContext); // Note, setting the token on the SegmentedStorageOperation is // key, this is how the iterator // will share the token across executions if (result != null) { this.setToken(result.getContinuationToken()); } return result; } }; return new LazySegmentedIterator(impl, this.blobServiceClient, this, options.getRetryPolicyFactory(), opContext); } /** * Returns a result segment containing a collection of blob items whose names begin with the specified prefix. * * @param prefix * The blob name prefix. This value must be preceded either by the name of the container or by the * absolute path to the container. * @param useFlatBlobListing * a value indicating whether the blob listing operation will list all blobs in a container in a flat * listing, or whether it will list blobs hierarchically, by virtual directory. * @param listingDetails * a EnumSet BlobListingDetails that indicates what items a listing operation will return. * @param maxResults * the maximum results to retrieve. * @param continuationToken * A continuation token returned by a previous listing operation. * @param options * An object that specifies any additional options for the request * @param taskReference * a reference to the encapsulating task * @param opContext * a tracking object for the operation * @return a result segment containing a collection of blob items whose names begin with the specified * @throws IllegalArgumentException * @throws URISyntaxException * @throws IOException * @throws StorageException * @throws InvalidKeyException * @throws XMLStreamException */ @DoesServiceRequest ResultSegment listBlobsCore(final String prefix, final boolean useFlatBlobListing, EnumSet listingDetails, final int maxResults, final ResultContinuation continuationToken, final BlobRequestOptions options, final StorageOperation> taskReference, final OperationContext opContext) throws URISyntaxException, IOException, StorageException, InvalidKeyException, XMLStreamException { Utility.assertContinuationType(continuationToken, ResultContinuationType.BLOB); Utility.assertNotNull("options", options); if (listingDetails == null) { listingDetails = EnumSet.noneOf(BlobListingDetails.class); } if (!useFlatBlobListing && listingDetails.contains(BlobListingDetails.SNAPSHOTS)) { throw new IllegalArgumentException( "Listing snapshots is only supported in flat mode (no delimiter). Consider setting useFlatBlobListing to true."); } final String delimiter = useFlatBlobListing ? null : this.blobServiceClient.getDirectoryDelimiter(); final BlobListingContext listingContext = new BlobListingContext(prefix, maxResults, delimiter, listingDetails); listingContext.setMarker(continuationToken != null ? continuationToken.getNextMarker() : null); final HttpURLConnection listBlobsRequest = BlobRequest.list(this.getTransformedAddress(), options.getTimeoutIntervalInMs(), listingContext, options, opContext); this.blobServiceClient.getCredentials().signRequest(listBlobsRequest, -1L); taskReference.setResult(ExecutionEngine.processRequest(listBlobsRequest, opContext)); if (taskReference.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { taskReference.setNonExceptionedRetryableFailure(true); return null; } final ListBlobsResponse response = new ListBlobsResponse(listBlobsRequest.getInputStream()); response.parseResponse(this.blobServiceClient, this); ResultContinuation newToken = null; if (response.getNextMarker() != null) { newToken = new ResultContinuation(); newToken.setNextMarker(response.getNextMarker()); newToken.setContinuationType(ResultContinuationType.BLOB); } final ResultSegment resSegment = new ResultSegment(response.getBlobs( this.blobServiceClient, this), maxResults, newToken); return resSegment; } /** * Returns a result segment of an enumerable collection of blob items in the container. * * @return A {@link ResultSegment} object that contains a segment of the enumerable collection of * {@link ListBlobItem} objects that represent the blob items in the container. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public ResultSegment listBlobsSegmented() throws StorageException { return this.listBlobsSegmented(null, false, EnumSet.noneOf(BlobListingDetails.class), -1, null, null, null); } /** * Returns a result segment containing a collection of blob items whose names begin with the specified prefix. * * @param prefix * A String that represents the prefix of the blob name. * * @return A {@link ResultSegment} object that contains a segment of the enumerable collection of * {@link ListBlobItem} objects that represent the blob items whose names begin with the specified prefix in * the container. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public ResultSegment listBlobsSegmented(final String prefix) throws StorageException { return this.listBlobsSegmented(prefix, false, EnumSet.noneOf(BlobListingDetails.class), -1, null, null, null); } /** * Returns a result segment containing a collection of blob items whose names begin with the specified prefix, using * the specified flat or hierarchical option, listing details options, request options, and operation context. * * @param prefix * A String that represents the prefix of the blob name. * @param useFlatBlobListing * true to indicate that the returned list will be flat; false to indicate that * the returned list will be hierarchical. * @param listingDetails * A java.util.EnumSet object that contains {@link BlobListingDetails} values that indicate * whether snapshots, metadata, and/or uncommitted blocks are returned. Committed blocks are always * returned. * @param maxResults * The maximum number of results to retrieve. * @param continuationToken * A {@link ResultContinuation} object that represents a continuation token returned by a previous * listing operation. * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @return A {@link ResultSegment} object that contains a segment of the enumerable collection of * {@link ListBlobItem} objects that represent the block items whose names begin with the specified prefix * in the container. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public ResultSegment listBlobsSegmented(final String prefix, final boolean useFlatBlobListing, final EnumSet listingDetails, final int maxResults, final ResultContinuation continuationToken, BlobRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); Utility.assertContinuationType(continuationToken, ResultContinuationType.BLOB); if (!useFlatBlobListing && listingDetails != null && listingDetails.contains(BlobListingDetails.SNAPSHOTS)) { throw new IllegalArgumentException( "Listing snapshots is only supported in flat mode (no delimiter). Consider setting useFlatBlobListing to true."); } final StorageOperation> impl = new StorageOperation>( options) { @Override public ResultSegment execute(final CloudBlobClient client, final CloudBlobContainer parent, final OperationContext opContext) throws Exception { return CloudBlobContainer.this.listBlobsCore(prefix, useFlatBlobListing, listingDetails, maxResults, continuationToken, (BlobRequestOptions) this.getRequestOptions(), this, opContext); } }; return ExecutionEngine.executeWithRetry(this.blobServiceClient, this, impl, options.getRetryPolicyFactory(), opContext); } /** * Returns an enumerable collection of containers for the service client associated with this container. * * @return An enumerable collection of {@link CloudBlobContainer} objects that represent the containers for the * service client associated with this container. */ @DoesServiceRequest public Iterable listContainers() { return this.blobServiceClient.listContainers(); } /** * Returns an enumerable collection of containers whose names begin with the specified prefix for the service client * associated with this container. * * @param prefix * A String that represents the container name prefix. * * @return An enumerable collection of {@link CloudBlobContainer} objects that represent the containers whose names * begin with the specified prefix for the service client associated with this container. */ @DoesServiceRequest public Iterable listContainers(final String prefix) { return this.blobServiceClient.listContainers(prefix); } /** * Returns an enumerable collection of containers whose names begin with the specified prefix for the service client * associated with this container, using the specified details setting, request options, and operation context. * * @param prefix * A String that represents the container name prefix. * @param detailsIncluded * A {@link ContainerListingDetails} value that indicates whether container metadata will be returned. * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @return An enumerable collection of {@link CloudBlobContainer} objects that represents the containers for the * service client associated with this container. */ @DoesServiceRequest public Iterable listContainers(final String prefix, final ContainerListingDetails detailsIncluded, final BlobRequestOptions options, final OperationContext opContext) { return this.blobServiceClient.listContainers(prefix, detailsIncluded, options, opContext); } /** * Returns a result segment of an enumerable collection of containers for the service client associated with this * container. * * @return A {@link ResultSegment} object that contains a segment of the enumerable collection of * {@link CloudBlobContainer} objects that represent the containers for the service client associated with * this container. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public ResultSegment listContainersSegmented() throws StorageException { return this.blobServiceClient.listContainersSegmented(); } /** * Returns a result segment of an enumerable collection of containers whose names begin with the specified prefix * for the service client associated with this container. * * @param prefix * A String that represents the blob name prefix. * * @return A {@link ResultSegment} object that contains a segment of the enumerable collection of * {@link CloudBlobContainer} objects that represent the containers whose names begin with the specified * prefix for the service client associated with this container. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public ResultSegment listContainersSegmented(final String prefix) throws StorageException { return this.blobServiceClient.listContainersSegmented(prefix); } /** * Returns a result segment containing a collection of containers whose names begin with the specified prefix for * the service client associated with this container, using the specified listing details options, request options, * and operation context. * * @param prefix * A String that represents the prefix of the container name. * @param detailsIncluded * A {@link ContainerListingDetails} object that indicates whether metadata is included. * @param maxResults * The maximum number of results to retrieve. * @param continuationToken * A {@link ResultContinuation} object that represents a continuation token returned by a previous * listing operation. * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @return A {@link ResultSegment} object that contains a segment of the enumerable collection of * {@link CloudBlobContainer} objects that represent the containers whose names begin with the specified * prefix for the service client associated with this container. * * @throws StorageException * If a storage service error occurred. * */ @DoesServiceRequest public ResultSegment listContainersSegmented(final String prefix, final ContainerListingDetails detailsIncluded, final int maxResults, final ResultContinuation continuationToken, final BlobRequestOptions options, final OperationContext opContext) throws StorageException { return this.blobServiceClient.listContainersSegmented(prefix, detailsIncluded, maxResults, continuationToken, options, opContext); } /** * Parse Uri for SAS (Shared access signature) information. * * Validate that no other query parameters are passed in. Any SAS information will be recorded as corresponding * credentials instance. If existingClient is passed in, any SAS information found will not be supported. Otherwise * a new client is created based on SAS information or as anonymous credentials. * * @param completeUri * The complete Uri. * @param existingClient * The client to use. * @param usePathStyleUris * If true, path style Uris are used. * @throws URISyntaxException * @throws StorageException */ private void parseQueryAndVerify(final URI completeUri, final CloudBlobClient existingClient, final boolean usePathStyleUris) throws URISyntaxException, StorageException { Utility.assertNotNull("completeUri", completeUri); if (!completeUri.isAbsolute()) { final String errorMessage = String.format( "Address '%s' is not an absolute address. Relative addresses are not permitted in here.", completeUri.toString()); throw new IllegalArgumentException(errorMessage); } this.uri = PathUtility.stripURIQueryAndFragment(completeUri); final HashMap queryParameters = PathUtility.parseQueryString(completeUri.getQuery()); final StorageCredentialsSharedAccessSignature sasCreds = SharedAccessSignatureHelper .parseQuery(queryParameters); if (sasCreds == null) { return; } final Boolean sameCredentials = existingClient == null ? false : Utility.areCredentialsEqual(sasCreds, existingClient.getCredentials()); if (existingClient == null || !sameCredentials) { this.blobServiceClient = new CloudBlobClient(new URI(PathUtility.getServiceClientBaseAddress(this.getUri(), usePathStyleUris)), sasCreds); } if (existingClient != null && !sameCredentials) { this.blobServiceClient .setPageBlobStreamWriteSizeInBytes(existingClient.getPageBlobStreamWriteSizeInBytes()); this.blobServiceClient.setSingleBlobPutThresholdInBytes(existingClient.getSingleBlobPutThresholdInBytes()); this.blobServiceClient.setStreamMinimumReadSizeInBytes(existingClient.getStreamMinimumReadSizeInBytes()); this.blobServiceClient.setWriteBlockSizeInBytes(existingClient.getWriteBlockSizeInBytes()); this.blobServiceClient.setConcurrentRequestCount(existingClient.getConcurrentRequestCount()); this.blobServiceClient.setDirectoryDelimiter(existingClient.getDirectoryDelimiter()); this.blobServiceClient.setRetryPolicyFactory(existingClient.getRetryPolicyFactory()); this.blobServiceClient.setTimeoutInMs(existingClient.getTimeoutInMs()); } } void updatePropertiesFromResponse(HttpURLConnection request) { String tempStr = request.getHeaderField(Constants.HeaderConstants.ETAG); // ETag if (!Utility.isNullOrEmpty(tempStr)) { this.getProperties().setEtag(tempStr); } // Last Modified if (0 != request.getLastModified()) { final Calendar lastModifiedCalendar = Calendar.getInstance(Utility.LOCALE_US); lastModifiedCalendar.setTimeZone(Utility.UTC_ZONE); lastModifiedCalendar.setTime(new Date(request.getLastModified())); this.getProperties().setLastModified(lastModifiedCalendar.getTime()); } } /** * Sets the metadata for the container. * * @param metadata * A java.util.HashMap object that represents the metadata being assigned to the container. */ public void setMetadata(final HashMap metadata) { this.metadata = metadata; } /** * Sets the name of the container. * * @param name * A String that represents the name being assigned to the container. */ protected void setName(final String name) { this.name = name; } /** * Sets the properties for the container. * * @param properties * A {@link BlobContainerProperties} object that represents the properties being assigned to the * container. */ protected void setProperties(final BlobContainerProperties properties) { this.properties = properties; } /** * Sets the URI of the container. * * @param uri * A java.net.URI object that represents the URI being assigned to the container. */ protected void setUri(final URI uri) { this.uri = uri; } /** * Uploads the container's metadata. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public void uploadMetadata() throws StorageException { this.uploadMetadata(null, null); } /** * Uploads the container's metadata using the specified request options and operation context. * * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public void uploadMetadata(BlobRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); final StorageOperation impl = new StorageOperation( options) { @Override public Void execute(final CloudBlobClient client, final CloudBlobContainer container, final OperationContext opContext) throws Exception { final HttpURLConnection request = ContainerRequest.setMetadata(container.uri, this.getRequestOptions() .getTimeoutIntervalInMs(), opContext); ContainerRequest.addMetadata(request, container.metadata, opContext); client.getCredentials().signRequest(request, 0L); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); } container.updatePropertiesFromResponse(request); return null; } }; ExecutionEngine .executeWithRetry(this.blobServiceClient, this, impl, options.getRetryPolicyFactory(), opContext); } /** * Uploads the container's permissions. * * @param permissions * A {@link BlobContainerPermissions} object that represents the permissions to upload. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public void uploadPermissions(final BlobContainerPermissions permissions) throws StorageException { this.uploadPermissions(permissions, null, null); } /** * Uploads the container's permissions using the specified request options and operation context. * * @param permissions * A {@link BlobContainerPermissions} object that represents the permissions to upload. * @param options * A {@link BlobRequestOptions} object that specifies any additional options for the request. Specifying * null will use the default request options from the associated service client ( * {@link CloudBlobClient}). * @param opContext * An {@link OperationContext} object that represents the context for the current operation. This object * is used to track requests to the storage service, and to provide additional runtime information about * the operation. * * @throws StorageException * If a storage service error occurred. */ @DoesServiceRequest public void uploadPermissions(final BlobContainerPermissions permissions, BlobRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } if (options == null) { options = new BlobRequestOptions(); } opContext.initialize(); options.applyDefaults(this.blobServiceClient); final StorageOperation impl = new StorageOperation( options) { @Override public Void execute(final CloudBlobClient client, final CloudBlobContainer container, final OperationContext opContext) throws Exception { final HttpURLConnection request = ContainerRequest.setAcl(container.uri, this.getRequestOptions() .getTimeoutIntervalInMs(), permissions.getPublicAccess(), opContext); final StringWriter outBuffer = new StringWriter(); ContainerRequest.writeSharedAccessIdentifiersToStream(permissions.getSharedAccessPolicies(), outBuffer); final byte[] aclBytes = outBuffer.toString().getBytes("UTF8"); client.getCredentials().signRequest(request, aclBytes.length); final OutputStream outStreamRef = request.getOutputStream(); outStreamRef.write(aclBytes); this.setResult(ExecutionEngine.processRequest(request, opContext)); if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_OK) { this.setNonExceptionedRetryableFailure(true); } container.updatePropertiesFromResponse(request); return null; } }; ExecutionEngine .executeWithRetry(this.blobServiceClient, this, impl, options.getRetryPolicyFactory(), opContext); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy