From 3ad35c20aa6207556bf1ac88ee97c4c3c28ee33d Mon Sep 17 00:00:00 2001 From: Josh Friedman Date: Mon, 15 May 2017 11:07:37 -0700 Subject: [PATCH 1/8] Revert "Revert changes for version 5.1.0" This reverts commit d34a89b1836b22ce0f800314a8b1a88dba24eb26. --- BreakingChanges.txt | 10 +- README.md | 28 +- .../blob/CloudBlobClientEncryptionTests.java | 37 +- .../storage/blob/CloudBlobClientTests.java | 4 +- .../storage/blob/CloudBlockBlobTests.java | 104 ++++-- .../storage/blob/CloudPageBlobTests.java | 26 ++ .../storage/file/CloudFileClientTests.java | 49 ++- .../storage/file/CloudFileDirectoryTests.java | 71 +++- .../storage/file/CloudFileShareTests.java | 195 ++++++++++- .../azure/storage/file/CloudFileTests.java | 175 +++++++++- .../azure/storage/file/FileTestHelper.java | 6 +- .../microsoft/azure/storage/Constants.java | 14 +- .../storage/StorageErrorCodeStrings.java | 5 + .../azure/storage/blob/BlobConstants.java | 17 +- .../storage/blob/BlobEncryptionPolicy.java | 17 +- .../azure/storage/blob/BlobRequest.java | 2 +- .../azure/storage/blob/CloudBlob.java | 13 +- .../azure/storage/blob/CloudPageBlob.java | 3 +- .../azure/storage/core/ExecutionEngine.java | 10 +- .../com/microsoft/azure/storage/core/SR.java | 3 +- .../core/SharedAccessSignatureHelper.java | 8 +- .../azure/storage/file/CloudFile.java | 180 +++++++--- .../azure/storage/file/CloudFileClient.java | 29 +- .../storage/file/CloudFileDirectory.java | 75 +++- .../azure/storage/file/CloudFileShare.java | 329 +++++++++++++++++- .../azure/storage/file/FileOutputStream.java | 8 +- .../azure/storage/file/FileRequest.java | 145 +++++++- .../azure/storage/file/FileResponse.java | 11 + .../storage/file/FileShareProperties.java | 25 +- .../azure/storage/file/ShareListHandler.java | 6 + .../storage/file/ShareListingDetails.java | 12 +- 31 files changed, 1403 insertions(+), 214 deletions(-) diff --git a/BreakingChanges.txt b/BreakingChanges.txt index 14d6dda4f..d3cb92e4f 100644 --- a/BreakingChanges.txt +++ b/BreakingChanges.txt @@ -1,4 +1,4 @@ -Changes in 5.1.1 +Changes in 5.1.1 OTHER * Reverted the code from 5.1.0 because it contained a regression and an accidental change. @@ -9,9 +9,9 @@ BLOB * getQualifiedStorageUri() has been deprecated. Please use getSnapshotQualifiedStorageUri() instead. This new function will return the blob including the snapshot (if present) and no SAS token. * Fixed a bug where copying from a blob that included a SAS token and a snapshot did not use the SAS token. - FILE +FILE * Fixed a bug where copying from a blob that included a SAS token and a snapshot did not use the SAS token. - + QUEUE * For addMessage() the CloudQueueMessage message passed in will be populated with the pop receipt, insertion/expiration time, and message ID. @@ -168,8 +168,8 @@ Changes in 0.5.0 OTHER * The packaging structure has changed to - 1. com.microsoft.windowsazure.storage – RetryPolicies, LocationMode, StorageException, Storage Credentials etc. Basically all public classes that are common across services. - 2. com.microsoft.windowsazure.storage.core – These classes are reserved for internal use and users never have to include this namespace in their projects. + 1. com.microsoft.windowsazure.storage � RetryPolicies, LocationMode, StorageException, Storage Credentials etc. Basically all public classes that are common across services. + 2. com.microsoft.windowsazure.storage.core � These classes are reserved for internal use and users never have to include this namespace in their projects. 3. com.microsoft.windowsazure.storage.blob 4. com.microsoft.windowsazure.storage.queue 5. com.microsoft.windowsazure.storage.table diff --git a/README.md b/README.md index 4ce0f71ba..0dc13920e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,10 @@ -#Microsoft Azure Storage SDK for Java +# Microsoft Azure Storage SDK for Java This project provides a client library in Java that makes it easy to consume Microsoft Azure Storage services. For documentation please see the Microsoft Azure [Java Developer Center](http://azure.microsoft.com/en-us/develop/java/) and the [JavaDocs](http://azure.github.io/azure-storage-java/). > If you are looking for the Azure Storage Android SDK, please visit [https://github.com/Azure/azure-storage-android](https://github.com/Azure/azure-storage-android). -#Features +# Features * Blob * Create/Read/Update/Delete containers * Create/Read/Update/Delete blobs @@ -19,10 +19,10 @@ This project provides a client library in Java that makes it easy to consume Mic * Batch operations * Advanced Table Operations -#Getting Started +# Getting Started -##Download -###Option 1: Via Maven +## Download +### Option 1: Via Maven To get the binaries of this library as distributed by Microsoft, ready for use within your project, you can use Maven. @@ -34,19 +34,19 @@ To get the binaries of this library as distributed by Microsoft, ready for use w ``` -###Option 2: Source Via Git +### Option 2: Source Via Git To get the source code of the SDK via git just type: git clone git://github.com/Azure/azure-storage-java.git - cd ./azure-storage-java/microsoft-azure-storage + cd ./azure-storage-java mvn compile -###Option 3: Source Zip +### Option 3: Source Zip To download a copy of the source code, click "Download ZIP" on the right side of the page or click [here](https://github.com/Azure/azure-storage-java/archive/master.zip). Unzip and navigate to the microsoft-azure-storage folder. -##Minimum Requirements +## Minimum Requirements * Java 1.6+ * [Jackson-Core](https://github.com/FasterXML/jackson-core) is used for JSON parsing. @@ -58,13 +58,13 @@ The two dependencies, [Jackson-Core](https://github.com/FasterXML/jackson-core) SLF4J is only needed if you enable logging through the OperationContext class. If you plan to use logging, please also download an [SLF4J binding](http://repo2.maven.org/maven2/org/slf4j/) which will link the SLF4J API with the logging implementation of your choice. Simple is a good default. See the [SLF4J user manual](http://www.slf4j.org/manual.html) for more information. -##Usage +## Usage To use this SDK to call Microsoft Azure storage services, you need to first [create an account](https://account.windowsazure.com/signup). Samples are provided in the microsoft-azure-storage-samples folder. The unit tests in microsoft-azure-storage-test can also be helpful. -##Code Sample +## Code Sample The following is a quick example on how to upload a file to azure blob and download it back. You may also download and view the samples in the microsoft-azure-storage-samples folder. For additional information on using the client libraries to access Azure services see the How To guides for [blobs](http://azure.microsoft.com/en-us/documentation/articles/storage-java-how-to-use-blob-storage/), [queues](http://azure.microsoft.com/en-us/documentation/articles/storage-java-how-to-use-queue-storage/), [tables](http://azure.microsoft.com/en-us/documentation/articles/storage-java-how-to-use-table-storage/) and the [general documentation](http://azure.microsoft.com/en-us/develop/java/). @@ -117,17 +117,17 @@ public class BlobSample { } ``` -#Need Help? +# Need Help? Be sure to check out the Microsoft Azure [Developer Forums on MSDN](http://social.msdn.microsoft.com/Forums/windowsazure/en-US/home?forum=windowsazuredata) or the [Developer Forums on Stack Overflow](http://stackoverflow.com/questions/tagged/azure+windows-azure-storage) if you have trouble with the provided code. -#Contribute Code or Provide Feedback +# Contribute Code or Provide Feedback If you would like to become an active contributor to this project please follow the instructions provided in [Azure Projects Contribution Guidelines](http://azure.github.io/guidelines/). If you encounter any bugs with the library please file an issue in the [Issues](https://github.com/Azure/azure-storage-java/issues) section of the project. -#Learn More +# Learn More * [Azure Developer Center](http://azure.microsoft.com/en-us/develop/java/) * [Azure Storage Service](http://azure.microsoft.com/en-us/documentation/services/storage/) diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobClientEncryptionTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobClientEncryptionTests.java index 1fdd8eec6..3d30f8641 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobClientEncryptionTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobClientEncryptionTests.java @@ -23,6 +23,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.net.URISyntaxException; +import java.nio.charset.Charset; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; @@ -143,7 +144,41 @@ else if (type == BlobType.APPEND_BLOB) { TestHelper.assertStreamsAreEqualAtIndex(stream, new ByteArrayInputStream(outputStream.toByteArray()), 0, 0, size, 2 * 1024); } - + + @Test + public void testDownloadUnencryptedBlobWithEncryptionPolicy() throws StorageException, IOException, URISyntaxException, NoSuchAlgorithmException + { + String blobName = BlobTestHelper.generateRandomBlobNameWithPrefix("test"); + CloudBlockBlob blob = container.getBlockBlobReference(blobName); + blob.deleteIfExists(); + + byte[] msg = "my message".getBytes(); + // Upload data without encryption + blob.uploadFromByteArray(msg, 0, msg.length); + + // Create options with encryption policy + BlobRequestOptions options = new BlobRequestOptions(); + options.setEncryptionPolicy(new BlobEncryptionPolicy(new RsaKey("myKey", 1024), null)); + options.setRequireEncryption(true); + + try { + blob.downloadText(Charset.defaultCharset().name(), null, options, null); + fail("Expect exception"); + } + catch (StorageException e) { + assertEquals(SR.ENCRYPTION_DATA_NOT_PRESENT_ERROR, e.getMessage()); + } + + byte[] buffer = new byte[msg.length]; + try { + blob.downloadRangeToByteArray(0, (long) buffer.length, buffer, 0, null, options, null); + fail("Expect exception"); + } + catch (StorageException e) { + assertEquals(SR.ENCRYPTION_DATA_NOT_PRESENT_ERROR, e.getMessage()); + } + } + @Test public void testBlobEncryptionWithFile() throws URISyntaxException, StorageException, IOException, InvalidKeyException, NoSuchAlgorithmException, NoSuchPaddingException { diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobClientTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobClientTests.java index 791776174..431bf42c2 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobClientTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobClientTests.java @@ -247,11 +247,11 @@ public void testSingleBlobPutThresholdInBytes() throws URISyntaxException, Stora try { bClient.getDefaultRequestOptions().setSingleBlobPutThresholdInBytes( BlobConstants.MAX_SINGLE_UPLOAD_BLOB_SIZE_IN_BYTES + 1); - fail("Cannot set upload blob threshold above 64 MB"); + fail("Cannot set upload blob threshold above 256 MB"); } catch (IllegalArgumentException e) { assertEquals( - "The argument is out of range. Argument name: singleBlobPutThresholdInBytes, Value passed: 67108865.", + "The argument is out of range. Argument name: singleBlobPutThresholdInBytes, Value passed: 268435457.", e.getMessage()); } diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlockBlobTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlockBlobTests.java index 5115e01aa..5027d672b 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlockBlobTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlockBlobTests.java @@ -33,8 +33,6 @@ import com.microsoft.azure.storage.file.SharedAccessFilePermissions; import com.microsoft.azure.storage.file.SharedAccessFilePolicy; -import junit.framework.Assert; - import org.junit.After; import org.junit.Before; import org.junit.Test; @@ -60,33 +58,11 @@ import java.util.Random; import java.util.TimeZone; -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.experimental.categories.Category; - -import com.microsoft.azure.storage.AccessCondition; -import com.microsoft.azure.storage.Constants; -import com.microsoft.azure.storage.NameValidator; -import com.microsoft.azure.storage.OperationContext; -import com.microsoft.azure.storage.RetryNoRetry; -import com.microsoft.azure.storage.SendingRequestEvent; -import com.microsoft.azure.storage.StorageCredentialsAnonymous; -import com.microsoft.azure.storage.StorageCredentialsSharedAccessSignature; import com.microsoft.azure.storage.StorageErrorCodeStrings; -import com.microsoft.azure.storage.StorageEvent; -import com.microsoft.azure.storage.StorageException; import com.microsoft.azure.storage.TestRunners.CloudTests; import com.microsoft.azure.storage.TestRunners.DevFabricTests; import com.microsoft.azure.storage.TestRunners.DevStoreTests; import com.microsoft.azure.storage.TestRunners.SlowTests; -import com.microsoft.azure.storage.core.Utility; -import com.microsoft.azure.storage.file.CloudFile; -import com.microsoft.azure.storage.file.CloudFileShare; -import com.microsoft.azure.storage.file.FileProperties; -import com.microsoft.azure.storage.file.FileTestHelper; -import com.microsoft.azure.storage.file.SharedAccessFilePermissions; -import com.microsoft.azure.storage.file.SharedAccessFilePolicy; import static org.junit.Assert.*; @@ -1018,6 +994,44 @@ public void testLargeBlobUploadFromStreamTest() throws URISyntaxException, Stora blockBlobRef.download(dstStream); BlobTestHelper.assertStreamsAreEqual(srcStream, new ByteArrayInputStream(dstStream.toByteArray())); } + + @Test + @Category({ DevFabricTests.class, DevStoreTests.class, SlowTests.class }) + public void testLargeSinglePutBlobTest() throws URISyntaxException, StorageException, IOException { + final String blockBlobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testBlockBlob"); + final String blockBlobName2 = BlobTestHelper.generateRandomBlobNameWithPrefix("testBlockBlob"); + final String blockBlobName3 = BlobTestHelper.generateRandomBlobNameWithPrefix("testBlockBlob"); + final CloudBlockBlob blob = this.container.getBlockBlobReference(blockBlobName); + final CloudBlockBlob blob2 = this.container.getBlockBlobReference(blockBlobName2); + final CloudBlockBlob blob3 = this.container.getBlockBlobReference(blockBlobName3); + BlobRequestOptions options = new BlobRequestOptions(); + options.setStoreBlobContentMD5(false); + options.setEncryptionPolicy(null); + try + { + byte[] buffer = BlobTestHelper.getRandomBuffer(256 * Constants.MB); + + OperationContext operationContext = new OperationContext(); + + blob.uploadFromByteArray(buffer, 0, 128 * Constants.MB, null, null, operationContext); + assertEquals(1, operationContext.getRequestResults().size()); + + options.setSingleBlobPutThresholdInBytes(256 * Constants.MB); + blob2.uploadFromByteArray(buffer, 0, 256 * Constants.MB, null, options, operationContext); + assertEquals(1, operationContext.getRequestResults().size()); + + // Reduce threshold and upload data greater than the single put blob upload threshold + options.setSingleBlobPutThresholdInBytes(Constants.MB); + blob3.uploadFromByteArray(buffer, 0, 3 * Constants.MB, null, options, operationContext); + assertTrue(operationContext.getRequestResults().size() > 1); + } + finally + { + blob.delete(); + blob2.delete(); + blob3.delete(); + } + } @Test @Category({ DevFabricTests.class, DevStoreTests.class }) @@ -1159,6 +1173,29 @@ public void testBlobUploadWithoutMD5Validation() throws URISyntaxException, Stor assertEquals("MDAwMDAwMDA=", blockBlobRef2.properties.getContentMD5()); } + @Test + @Category({ DevFabricTests.class, DevStoreTests.class }) + public void testVerifyTransactionalMD5ValidationMissingOverallMD5() throws URISyntaxException, StorageException, IOException { + final String blockBlobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testBlockBlob"); + final CloudBlockBlob blockBlobRef = this.container.getBlockBlobReference(blockBlobName); + + final int length = 2 * 1024 * 1024; + ByteArrayInputStream srcStream = BlobTestHelper.getRandomDataStream(length); + BlobRequestOptions options = new BlobRequestOptions(); + options.setSingleBlobPutThresholdInBytes(1024*1024); + options.setDisableContentMD5Validation(true); + options.setStoreBlobContentMD5(false); + + blockBlobRef.upload(srcStream, -1, null, options, null); + + options.setDisableContentMD5Validation(false); + options.setStoreBlobContentMD5(true); + options.setUseTransactionalContentMD5(true); + final CloudBlockBlob blockBlobRef2 = this.container.getBlockBlobReference(blockBlobName); + blockBlobRef2.downloadRange(1024, (long)1024, new ByteArrayOutputStream(), null, options, null); + assertNull(blockBlobRef2.getProperties().getContentMD5()); + } + @Test @Category({ DevFabricTests.class, DevStoreTests.class }) public void testBlockBlobUploadContentMD5() throws URISyntaxException, StorageException, IOException { @@ -1198,7 +1235,7 @@ public void eventOccurred(SendingRequestEvent eventArg) { } }; - length = 33 * Constants.MB; + length = BlobConstants.DEFAULT_SINGLE_BLOB_PUT_THRESHOLD_IN_BYTES + 1; srcStream = BlobTestHelper.getRandomDataStream(length); sendingRequestEventContext.getSendingRequestEventHandler().addListener(event); @@ -1709,6 +1746,23 @@ public void testBlobConditionalAccess() throws StorageException, IOException, UR newETag = blob.getProperties().getEtag(); assertFalse("ETage should be modified on write metadata", newETag.equals(currentETag)); } + + @Test + public void testBlobExceedMaxRange() throws URISyntaxException, StorageException, IOException + { + CloudBlockBlob blob = container.getBlockBlobReference("blockblob4"); + blob.deleteIfExists(); + + byte[] msg = "my message".getBytes("UTF-8"); + blob.uploadFromByteArray(msg, 0, msg.length); + + byte[] buffer = new byte[msg.length + 5]; + + blob.downloadRangeToByteArray(0, (long) buffer.length, buffer, 0, null, null, null); + String expected = new String (msg, "UTF-8"); + String actual = new String(buffer, "UTF-8").substring(0, 10); + assertEquals(expected, actual); + } @Test @Category({ DevFabricTests.class, DevStoreTests.class }) diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudPageBlobTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudPageBlobTests.java index d292bd749..9dd0e6b26 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudPageBlobTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudPageBlobTests.java @@ -211,6 +211,32 @@ public void testPageBlobDownloadRangeValidationTest() throws StorageException, U assertEquals(100, downloadLength); } + /** + * Test requesting stored content MD5 with OpenWriteExisting(). + * + * @throws URISyntaxException + * @throws StorageException + */ + @Test + public void testPageOpenWriteExistingWithMD5() throws URISyntaxException, StorageException, IOException { + final String pageBlobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testPageBlob"); + final CloudPageBlob pageBlobRef = this.container.getPageBlobReference(pageBlobName); + pageBlobRef.create(512); + + BlobRequestOptions options = new BlobRequestOptions(); + options.setStoreBlobContentMD5(true); + options.setDisableContentMD5Validation(false); + + try + { + pageBlobRef.openWriteExisting(null, options, null); + fail("Expect failure due to requesting MD5 calculation"); + } + catch (IllegalArgumentException e) + { + } + } + @Test public void testPageBlobUploadFromStreamTest() throws URISyntaxException, StorageException, IOException { final String pageBlobName = BlobTestHelper.generateRandomBlobNameWithPrefix("testPageBlob"); diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileClientTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileClientTests.java index f90b148a8..f83e4d588 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileClientTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileClientTests.java @@ -28,6 +28,8 @@ import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.EnumSet; +import java.util.HashMap; import java.util.UUID; import static org.junit.Assert.*; @@ -64,8 +66,8 @@ public void testListSharesTest() throws StorageException, URISyntaxException { ResultContinuation token = null; do { - ResultSegment segment = fileClient.listSharesSegmented(prefix, ShareListingDetails.ALL, - 15, token, null, null); + ResultSegment segment = fileClient.listSharesSegmented(prefix, + ShareListingDetails.ALL, 15, token, null, null); for (final CloudFileShare share : segment.getResults()) { share.downloadAttributes(); @@ -112,4 +114,47 @@ public void testListSharesMaxResultsValidationTest() throws StorageException, UR } assertNotNull(fileClient.listSharesSegmented("thereshouldntbeanyshareswiththisprefix")); } + + //@Test + public void testListSharesWithSnapshot() throws StorageException, URISyntaxException { + CloudFileClient fileClient = FileTestHelper.createCloudFileClient(); + CloudFileShare share = fileClient.getShareReference(UUID.randomUUID().toString()); + share.create(); + + HashMap shareMeta = new HashMap(); + shareMeta.put("key1", "value1"); + share.setMetadata(shareMeta); + share.uploadMetadata(); + + CloudFileShare snapshot = share.createSnapshot(); + HashMap meta2 = new HashMap(); + meta2.put("key2", "value2"); + share.setMetadata(meta2); + share.uploadMetadata(); + + CloudFileClient client = FileTestHelper.createCloudFileClient(); + Iterable listResult = client.listShares(share.name, ShareListingDetails.ALL, null, null); + + int count = 0; + boolean originalFound = false; + boolean snapshotFound = false; + for (CloudFileShare listShareItem : listResult) { + if (listShareItem.getName().equals(share.getName()) && !listShareItem.isSnapshot() && !originalFound) + { + count++; + originalFound = true; + assertEquals(share.getMetadata(), listShareItem.getMetadata()); + assertEquals(share.getStorageUri(), listShareItem.getStorageUri()); + } + else if (listShareItem.getName().equals(share.getName()) && + listShareItem.isSnapshot() && !snapshotFound) { + count++; + snapshotFound = true; + assertEquals(snapshot.getMetadata(), listShareItem.getMetadata()); + assertEquals(snapshot.getStorageUri(), listShareItem.getStorageUri()); + } + } + + assertEquals(2, count); + } } \ No newline at end of file diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java index fbf9e898e..f9e87412c 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java @@ -27,12 +27,14 @@ import com.microsoft.azure.storage.TestRunners.DevStoreTests; import com.microsoft.azure.storage.core.PathUtility; import com.microsoft.azure.storage.core.SR; +import com.microsoft.azure.storage.core.UriQueryBuilder; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; +import java.util.HashMap; import org.junit.After; import org.junit.Assert; @@ -460,7 +462,7 @@ public void testCloudFileDirectoryInvalidMetadata() throws StorageException, URI testMetadataFailures(directory, "key1", "\n \t", false); } - private static void testMetadataFailures(CloudFileDirectory directory, String key, String value, boolean badKey) { + private static void testMetadataFailures(CloudFileDirectory directory, String key, String value, boolean badKey) throws URISyntaxException { directory.getMetadata().put(key, value); try { directory.uploadMetadata(); @@ -478,6 +480,71 @@ private static void testMetadataFailures(CloudFileDirectory directory, String ke directory.getMetadata().remove(key); } + //@Test + public void testUnsupportedDirectoryApisWithinShareSnapshot() throws StorageException, URISyntaxException { + CloudFileShare snapshot = this.share.createSnapshot(); + CloudFileDirectory rootDir = snapshot.getRootDirectoryReference(); + try { + rootDir.create(); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + rootDir.delete(); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + rootDir.uploadMetadata(); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + + snapshot.delete(); + } + + //@Test + public void testSupportedDirectoryApisInShareSnapshot() throws StorageException, URISyntaxException { + CloudFileDirectory dir = this.share.getRootDirectoryReference().getDirectoryReference("dir1"); + dir.deleteIfExists(); + dir.create(); + HashMap meta = new HashMap(); + meta.put("key1", "value1"); + dir.setMetadata(meta); + dir.uploadMetadata(); + CloudFileShare snapshot = this.share.createSnapshot(); + CloudFileDirectory snapshotDir = snapshot.getRootDirectoryReference().getDirectoryReference("dir1"); + + HashMap meta2 = new HashMap(); + meta2.put("key2", "value2"); + dir.setMetadata(meta2); + dir.uploadMetadata(); + snapshotDir.downloadAttributes(); + + assertTrue(snapshotDir.getMetadata().size() == 1 && snapshotDir.getMetadata().get("key1").equals("value1")); + assertNotNull(snapshotDir.getProperties().getEtag()); + + dir.downloadAttributes(); + assertTrue(dir.getMetadata().size() == 1 && dir.getMetadata().get("key2").equals("value2")); + assertNotNull(dir.getProperties().getEtag()); + assertNotEquals(dir.getProperties().getEtag(), snapshotDir.getProperties().getEtag()); + + final UriQueryBuilder uriBuilder = new UriQueryBuilder(); + uriBuilder.add("sharesnapshot", snapshot.snapshotID); + uriBuilder.add("restype", "directory"); + CloudFileDirectory snapshotDir2 = new CloudFileDirectory(uriBuilder.addToURI(dir.getUri()), this.share.getServiceClient().getCredentials()); + assertEquals(snapshot.snapshotID, snapshotDir2.getShare().snapshotID); + assertTrue(snapshotDir2.exists()); + + snapshot.delete(); + } + /* [TestMethod] [Description("CloudFileDirectory deleting a directory using conditional access")] @@ -807,6 +874,8 @@ public void eventOccurred(SendingRequestEvent eventArg) { } catch (StorageException e) { fail("Delete should succeed."); + } catch (URISyntaxException e) { + fail("Delete should succeed."); } } } diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileShareTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileShareTests.java index d7e62ed1a..46a84aac4 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileShareTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileShareTests.java @@ -25,6 +25,8 @@ import com.microsoft.azure.storage.TestRunners.DevFabricTests; import com.microsoft.azure.storage.TestRunners.DevStoreTests; import com.microsoft.azure.storage.TestRunners.SlowTests; +import com.microsoft.azure.storage.core.SR; +import com.microsoft.azure.storage.core.UriQueryBuilder; import org.junit.After; import org.junit.Assert; @@ -32,6 +34,7 @@ import org.junit.Test; import org.junit.experimental.categories.Category; +import java.io.ByteArrayInputStream; import java.io.IOException; import java.net.HttpURLConnection; import java.net.URISyntaxException; @@ -50,7 +53,6 @@ @Category({ DevFabricTests.class, DevStoreTests.class, CloudTests.class }) public class CloudFileShareTests { - protected static CloudFileClient client; protected CloudFileShare share; @Before @@ -427,6 +429,7 @@ public void testCloudFileShareQuota() throws StorageException, URISyntaxExceptio try { shareQuota = FileConstants.MAX_SHARE_QUOTA + 1; this.share.getProperties().setShareQuota(shareQuota); + this.share.uploadProperties(); fail(); } catch (IllegalArgumentException e) { assertEquals(String.format(SR.PARAMETER_NOT_IN_RANGE, "Share Quota", 1, FileConstants.MAX_SHARE_QUOTA), @@ -491,6 +494,196 @@ public void eventOccurred(SendingRequestEvent eventArg) { assertTrue(this.share.deleteIfExists(null, null, ctx)); } + //@Test + public void testCreateShareSnapshot() throws StorageException, URISyntaxException, IOException { + // create share with metadata + this.share.create(); + assertTrue(this.share.exists()); + HashMap shareMeta = new HashMap(); + shareMeta.put("key1", "value1"); + this.share.setMetadata(shareMeta); + this.share.uploadMetadata(); + + CloudFileDirectory dir1 = this.share.getRootDirectoryReference().getDirectoryReference("dir1"); + dir1.create(); + CloudFile file1 = dir1.getFileReference("file1"); + file1.create(1024); + ByteArrayInputStream srcStream = FileTestHelper.getRandomDataStream(1024); + file1.upload(srcStream, 1024); + + // create directory with metadata + HashMap dirMeta = new HashMap(); + dirMeta.put("key2", "value2"); + dir1.setMetadata(dirMeta); + dir1.uploadMetadata(); + + // verify that exists() call on snapshot populates metadata + CloudFileShare snapshot = this.share.createSnapshot(); + CloudFileClient client = FileTestHelper.createCloudFileClient(); + CloudFileShare snapshotRef = client.getShareReference(snapshot.name, snapshot.snapshotID); + assertTrue(snapshotRef.exists()); + assertTrue(snapshotRef.getMetadata().size() == 1 && snapshotRef.getMetadata().get("key1").equals("value1")); + + // verify that downloadAttributes() populates metadata + CloudFileShare snapshotRef2 = client.getShareReference(snapshot.name, snapshot.snapshotID); + snapshotRef2.downloadAttributes(); + snapshot.downloadAttributes(); + assertTrue(snapshotRef2.getMetadata().size() == 1 && snapshotRef2.getMetadata().get("key1").equals("value1")); + assertTrue(snapshot.getMetadata().size() == 1 && snapshot.getMetadata().get("key1").equals("value1")); + + // verify that exists() populates the metadata + CloudFileDirectory snapshotDir1 = snapshot.getRootDirectoryReference().getDirectoryReference("dir1"); + snapshotDir1.exists(); + assertTrue(snapshotDir1.getMetadata().size() == 1 && snapshotDir1.getMetadata().get("key2").equals("value2")); + + // verify that downloadAttributes() populates the metadata + CloudFileDirectory snapshotDir2 = snapshot.getRootDirectoryReference().getDirectoryReference("dir1"); + snapshotDir2.downloadAttributes(); + assertTrue(snapshotDir2.getMetadata().size() == 1 && snapshotDir2.getMetadata().get("key2").equals("value2")); + + // create snapshot with metadata + HashMap shareMeta2 = new HashMap(); + shareMeta2.put("abc", "def"); + CloudFileShare snapshotRef3 = this.share.createSnapshot(shareMeta2, null, null, null); + CloudFileShare snapshotRef4 = client.getShareReference(snapshotRef3.name, snapshotRef3.snapshotID); + assertTrue(snapshotRef4.exists()); + assertTrue(snapshotRef4.getMetadata().size() == 1 && snapshotRef4.getMetadata().get("abc").equals("def")); + + final UriQueryBuilder uriBuilder = new UriQueryBuilder(); + uriBuilder.add("sharesnapshot", snapshot.snapshotID); +// CloudFileShare snapshotRef5 = new CloudFileShare(uriBuilder.addToURI(this.share.getUri()), +// this.share.getServiceClient().getCredentials(), null); +// assertEquals(snapshot.snapshotID, snapshotRef5.snapshotID); +// assertTrue(snapshotRef5.exists()); + + snapshot.delete(); + } + + //@Test + public void testDeleteShareSnapshotOptions() throws StorageException, URISyntaxException, IOException { + // create share with metadata + this.share.create(); + assertTrue(this.share.exists()); + + // verify that exists() call on snapshot populates metadata + CloudFileShare snapshot = this.share.createSnapshot(); + CloudFileClient client = FileTestHelper.createCloudFileClient(); + CloudFileShare snapshotRef = client.getShareReference(snapshot.name, snapshot.snapshotID); + assertTrue(snapshotRef.exists()); + + try { + share.delete(); + } + catch (final StorageException e) { + assertEquals(StorageErrorCodeStrings.SHARE_HAS_SNAPSHOTS, e.getErrorCode()); + } + + share.delete(DeleteShareSnapshotsOption.INCLUDE_SNAPSHOTS, null, null, null); + assertFalse(share.exists()); + assertFalse(snapshot.exists()); + } + + //@Test + public void testListFilesAndDirectoriesWithinShareSnapshot() throws StorageException, URISyntaxException { + this.share.create(); + + CloudFileDirectory myDir = this.share.getRootDirectoryReference().getDirectoryReference("mydir"); + myDir.create(); + myDir.getFileReference("myfile").create(1024); + myDir.getDirectoryReference("yourDir").create(); + assertTrue(this.share.exists()); + + CloudFileShare snapshot = this.share.createSnapshot(); + CloudFileClient client = FileTestHelper.createCloudFileClient(); + CloudFileShare snapshotRef = client.getShareReference(snapshot.name, snapshot.snapshotID); + + Iterable listResult = snapshotRef.getRootDirectoryReference().listFilesAndDirectories(); + int count = 0; + for (ListFileItem listFileItem : listResult) { + count++; + assertEquals("mydir", ((CloudFileDirectory) listFileItem).getName()); + } + + assertEquals(1, count); + + count = 0; + listResult = snapshotRef.getRootDirectoryReference().getDirectoryReference("mydir").listFilesAndDirectories(); + for (ListFileItem listFileItem : listResult) { + if (listFileItem instanceof CloudFileDirectory) { + count++; + assertEquals("yourDir", ((CloudFileDirectory) listFileItem).getName()); + } + else { + count++; + assertEquals("myfile", ((CloudFile) listFileItem).getName()); + } + } + + assertEquals(2, count); + + snapshot.delete(); + } + + //@Test + public void testUnsupportedApisShareSnapshot() throws StorageException, URISyntaxException { + CloudFileClient client = FileTestHelper.createCloudFileClient(); + this.share.create(); + this.share.downloadPermissions(); + CloudFileShare snapshot = this.share.createSnapshot(); + try { + snapshot.createSnapshot(); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } +// try { +// new CloudFileShare(snapshot.getQualifiedUri(), client.getCredentials(), "2016-10-24T16:37:17.0000000Z"); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.SNAPSHOT_QUERY_OPTION_ALREADY_DEFINED, e.getMessage()); +// } + try { + snapshot.downloadPermissions(); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + snapshot.getStats(); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + snapshot.uploadMetadata(); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + FileSharePermissions permissions = new FileSharePermissions(); + snapshot.uploadPermissions(permissions); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + snapshot.uploadProperties(); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + + snapshot.delete(); + } + private static void assertPermissionsEqual(FileSharePermissions expected, FileSharePermissions actual) { HashMap expectedPolicies = expected.getSharedAccessPolicies(); HashMap actualPolicies = actual.getSharedAccessPolicies(); diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java index 9d165fb3a..9bf77cfb9 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java @@ -1,4 +1,4 @@ -/** +/** * Copyright Microsoft Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); @@ -38,6 +38,9 @@ import com.microsoft.azure.storage.TestRunners.DevFabricTests; import com.microsoft.azure.storage.TestRunners.DevStoreTests; import com.microsoft.azure.storage.TestRunners.SlowTests; +import com.microsoft.azure.storage.core.SR; +import com.microsoft.azure.storage.core.UriQueryBuilder; +import com.microsoft.azure.storage.core.Utility; import org.junit.After; import org.junit.Before; @@ -48,6 +51,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.lang.reflect.Constructor; import java.net.HttpURLConnection; import java.net.URI; @@ -724,6 +728,45 @@ public void testFileUploadMD5Validation() throws URISyntaxException, StorageExce assertEquals(calculatedMD5, fileRef2.getProperties().getContentMD5()); } + @Test + public void testFileContentMD5NewFileTest() throws URISyntaxException, StorageException, IOException { + final String fileName = FileTestHelper.generateRandomFileName(); + final CloudFile file = this.share.getRootDirectoryReference().getFileReference(fileName); + + FileRequestOptions options = new FileRequestOptions(); + options.setStoreFileContentMD5(true); + options.setDisableContentMD5Validation(false); + + File tempFile = File.createTempFile("sourceFile", ".tmp"); + file.uploadFromFile(tempFile.getAbsolutePath(), null, options, null); + } + + /** + * Test requesting stored content MD5 with OpenWriteExisting(). + * + * @throws URISyntaxException + * @throws StorageException + */ + @Test + public void testCloudFileOpenWriteExistingWithMD5() throws URISyntaxException, StorageException, IOException { + String fileName = FileTestHelper.generateRandomFileName(); + final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); + fileRef.create(512); + + FileRequestOptions options = new FileRequestOptions(); + options.setStoreFileContentMD5(true); + options.setDisableContentMD5Validation(false); + + try + { + fileRef.openWriteExisting(null, options, null); + fail("Expect failure due to requesting MD5 calculation"); + } + catch (IllegalArgumentException e) + { + } + } + @Test public void testFileEmptyHeaderSigningTest() throws URISyntaxException, StorageException, IOException { final String fileName = FileTestHelper.generateRandomFileName(); @@ -994,7 +1037,7 @@ private void doUploadFromByteArrayTest(CloudFile file, int bufferSize, int buffe } } - private void doUploadDownloadFileTest(CloudFile file, int fileSize) throws IOException, StorageException { + private void doUploadDownloadFileTest(CloudFile file, int fileSize) throws IOException, StorageException, URISyntaxException { File sourceFile = File.createTempFile("sourceFile", ".tmp"); File destinationFile = new File(sourceFile.getParentFile(), "destinationFile.tmp"); @@ -1081,6 +1124,28 @@ public void testCloudFileUploadRange() throws URISyntaxException, StorageExcepti inputStream = new ByteArrayInputStream(buffer); } + + @Test + @Category({ DevFabricTests.class, DevStoreTests.class }) + public void testVerifyTransactionalMD5ValidationMissingOverallMD5() throws URISyntaxException, StorageException, IOException { + final String fileName = FileTestHelper.generateRandomFileName(); + final CloudFile fileRef = this.share.getRootDirectoryReference().getFileReference(fileName); + + final int length = 3*1024; + ByteArrayInputStream srcStream = BlobTestHelper.getRandomDataStream(length); + FileRequestOptions options = new FileRequestOptions(); + options.setDisableContentMD5Validation(true); + options.setStoreFileContentMD5(false); + + fileRef.upload(srcStream, length, null, options, null); + + options.setDisableContentMD5Validation(false); + options.setStoreFileContentMD5(true); + options.setUseTransactionalContentMD5(true); + final CloudFile fileRef2 = this.share.getRootDirectoryReference().getFileReference(fileName); + fileRef2.downloadRange(1024, (long)1024, new ByteArrayOutputStream(), null, options, null); + assertNull(fileRef2.getProperties().getContentMD5()); + } /** * Test clearing file ranges. @@ -1349,6 +1414,8 @@ public void eventOccurred(SendingRequestEvent eventArg) { } catch (StorageException e) { fail("Delete should succeed."); + } catch (URISyntaxException e) { + fail("Delete should succeed."); } } } @@ -1397,8 +1464,8 @@ public void testFileGetRangeContentMD5Bounds() throws StorageException, IOExcept FileRequestOptions options = new FileRequestOptions(); OperationContext opContext = new OperationContext(); try { - FileRequest.getFile(file.getUri(), options, opContext, null, 0L, 4L * Constants.MB, true); - FileRequest.getFile(file.getUri(), options, opContext, null, 0L, 4L * Constants.MB + 1, true); + FileRequest.getFile(file.getUri(), options, opContext, null, null, 0L, 4L * Constants.MB, true); + FileRequest.getFile(file.getUri(), options, opContext, null, null, 0L, 4L * Constants.MB + 1, true); fail("The request for range ContentMD5 should have thrown an Exception for exceeding the limit."); } catch (IllegalArgumentException e) @@ -1551,4 +1618,104 @@ private void doCloudFileCopy(boolean sourceIsSas, boolean destinationIsSas) destination.delete(); source.delete(); } + + //@Test + public void testUnsupportedFileApisWithinShareSnapshot() throws StorageException, URISyntaxException { + CloudFileShare snapshot = this.share.createSnapshot(); + CloudFile file = snapshot.getRootDirectoryReference().getFileReference("file"); + + try { + file.create(1024); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + file.delete(); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + file.uploadMetadata(); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + file.abortCopy(null); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + file.clearRange(0, 512); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + file.startCopy(file); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } + try { + file.upload(null, 512); + fail("Shouldn't get here"); + } + catch (IllegalArgumentException e) { + assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); + } catch (IOException e) { + fail("Shouldn't get here"); + } + + snapshot.delete(); + } + + //@Test + public void testSupportedFileApisInShareSnapshot() throws StorageException, URISyntaxException, UnsupportedEncodingException { + CloudFileDirectory dir = this.share.getRootDirectoryReference().getDirectoryReference("dir1"); + dir.deleteIfExists(); + dir.create(); + CloudFile file = dir.getFileReference("file"); + file.create(1024); + + HashMap meta = new HashMap(); + meta.put("key1", "value1"); + file.setMetadata(meta); + file.uploadMetadata(); + + CloudFileShare snapshot = this.share.createSnapshot(); + CloudFile snapshotFile = snapshot.getRootDirectoryReference() + .getDirectoryReference("dir1").getFileReference("file"); + + HashMap meta2 = new HashMap(); + meta2.put("key2", "value2"); + file.setMetadata(meta2); + file.uploadMetadata(); + snapshotFile.downloadAttributes(); + + assertTrue(snapshotFile.getMetadata().size() == 1 && snapshotFile.getMetadata().get("key1").equals("value1")); + assertNotNull(snapshotFile.getProperties().getEtag()); + + file.downloadAttributes(); + assertTrue(file.getMetadata().size() == 1 && file.getMetadata().get("key2").equals("value2")); + assertNotNull(file.getProperties().getEtag()); + assertNotEquals(file.getProperties().getEtag(), snapshotFile.getProperties().getEtag()); + + final UriQueryBuilder uriBuilder = new UriQueryBuilder(); + uriBuilder.add("sharesnapshot", snapshot.snapshotID); + CloudFile snapshotFile2 = new CloudFile(uriBuilder.addToURI(file.getUri()), this.share.getServiceClient().getCredentials()); + assertEquals(snapshot.snapshotID, snapshotFile2.getShare().snapshotID); + assertTrue(snapshotFile2.exists()); + + snapshot.delete(); + } } \ No newline at end of file diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/FileTestHelper.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/FileTestHelper.java index 6d4e90c35..4e7ca4236 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/FileTestHelper.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/FileTestHelper.java @@ -97,7 +97,7 @@ static StorageUri ensureTrailingSlash(StorageUri uri) throws URISyntaxException } protected static void doDownloadTest(CloudFile file, int fileSize, int bufferSize, int bufferOffset) - throws StorageException, IOException { + throws StorageException, IOException, URISyntaxException { final Random randGenerator = new Random(); final byte[] buffer = new byte[fileSize]; randGenerator.nextBytes(buffer); @@ -119,7 +119,7 @@ protected static void doDownloadTest(CloudFile file, int fileSize, int bufferSiz } protected static void doDownloadRangeToByteArrayTest(CloudFile file, int fileSize, int bufferSize, - int bufferOffset, Long fileOffset, Long length) throws IOException, StorageException { + int bufferOffset, Long fileOffset, Long length) throws IOException, StorageException, URISyntaxException { final Random randGenerator = new Random(); final byte[] buffer = new byte[fileSize]; randGenerator.nextBytes(buffer); @@ -153,7 +153,7 @@ protected static void doDownloadRangeToByteArrayTest(CloudFile file, int fileSiz } } - protected static void doDownloadRangeToByteArrayNegativeTests(CloudFile file) throws StorageException, IOException { + protected static void doDownloadRangeToByteArrayNegativeTests(CloudFile file) throws StorageException, IOException, URISyntaxException { int fileLength = 1024; int resultBufSize = 1024; final Random randGenerator = new Random(); diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/Constants.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/Constants.java index 7471c5d4b..556c88456 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/Constants.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/Constants.java @@ -500,7 +500,12 @@ public static class HeaderConstants { * The blob sequence number equal condition header. */ public static final String IF_SEQUENCE_NUMBER_EQUAL = PREFIX_FOR_STORAGE_HEADER + "if-sequence-number-eq"; - + + /** + * Specifies snapshots are to be included. + */ + public static final String INCLUDE_SNAPSHOTS_VALUE = "include"; + /** * The header that specifies the lease action to perform */ @@ -636,7 +641,7 @@ public static class HeaderConstants { /** * The current storage version header value. */ - public static final String TARGET_STORAGE_VERSION = "2016-05-31"; + public static final String TARGET_STORAGE_VERSION = "2016-10-16"; /** * The header that specifies the next visible time for a queue message. @@ -808,6 +813,11 @@ public static class QueryConstants { */ public static final String SNAPSHOT = "snapshot"; + /** + * The query component for snapshot time. + */ + public static final String SHARE_SNAPSHOT = "sharesnapshot"; + /** * The query component for the SAS start partition key. */ diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/StorageErrorCodeStrings.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/StorageErrorCodeStrings.java index 5a1d59619..cece90e8f 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/StorageErrorCodeStrings.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/StorageErrorCodeStrings.java @@ -569,6 +569,11 @@ public final class StorageErrorCodeStrings { */ public static final String SHARE_DISABLED = "ShareDisabled"; + /** + * The specified share contains snapshots. + */ + public static final String SHARE_HAS_SNAPSHOTS = "ShareHasSnapshots"; + /** * The specified share was not found. */ diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobConstants.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobConstants.java index 2e3340717..6df87f96d 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobConstants.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobConstants.java @@ -151,16 +151,6 @@ final class BlobConstants { */ public static final int DEFAULT_POLLING_INTERVAL_IN_SECONDS = 30; - /** - * The default maximum size, in bytes, of a blob before it must be separated into blocks. - */ - public static final int DEFAULT_SINGLE_BLOB_PUT_THRESHOLD_IN_BYTES = 32 * Constants.MB; - - /** - * Specifies snapshots are to be included. - */ - public static final String INCLUDE_SNAPSHOTS_VALUE = "include"; - /** * XML element for the latest. */ @@ -170,7 +160,12 @@ final class BlobConstants { * The maximum size, in bytes, of a blob before it must be separated into blocks */ // Note if this is updated then Constants.MAX_MARK_LENGTH needs to be as well. - public static final int MAX_SINGLE_UPLOAD_BLOB_SIZE_IN_BYTES = 64 * Constants.MB; + public static final int MAX_SINGLE_UPLOAD_BLOB_SIZE_IN_BYTES = 256 * Constants.MB; + + /** + * The default maximum size, in bytes, of a blob before it must be separated into blocks. + */ + public static final int DEFAULT_SINGLE_BLOB_PUT_THRESHOLD_IN_BYTES = MAX_SINGLE_UPLOAD_BLOB_SIZE_IN_BYTES / 2; /** * Specifies the page blob type. diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobEncryptionPolicy.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobEncryptionPolicy.java index ea2ec36ae..ac77d8f47 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobEncryptionPolicy.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobEncryptionPolicy.java @@ -130,15 +130,8 @@ public void setKeyResolver(IKeyResolver keyResolver) { OutputStream decryptBlob(OutputStream userProvidedStream, Map metadata, Boolean requireEncryption, byte[] iv, boolean noPadding) throws StorageException { Utility.assertNotNull("metadata", metadata); - - // If encryption policy is set but the encryption metadata is absent, throw - // an exception. String encryptionDataString = metadata.get("encryptiondata"); - if (requireEncryption != null && requireEncryption && encryptionDataString == null) - { - throw new StorageException(StorageErrorCodeStrings.DECRYPTION_ERROR, SR.ENCRYPTION_DATA_NOT_PRESENT_ERROR, null); - } - + try { if (encryptionDataString != null) { @@ -234,6 +227,14 @@ static OutputStream wrapUserStreamWithDecryptStream(CloudBlob blob, OutputStream BlobRequestOptions options, Map metadata, long blobLength, boolean rangeRead, Long endOffset, Long userSpecifiedLength, int discardFirst, boolean bufferIV) throws StorageException { + // If encryption policy is set but the encryption metadata is absent, throw + // an exception. + String encryptionDataString = metadata.get("encryptiondata"); + if (options.requireEncryption() != null && options.requireEncryption() && encryptionDataString == null) + { + throw new StorageException(StorageErrorCodeStrings.DECRYPTION_ERROR, SR.ENCRYPTION_DATA_NOT_PRESENT_ERROR, null); + } + if (!rangeRead) { // The user provided stream should be wrapped in a TruncatingNonCloseableStream in order to diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobRequest.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobRequest.java index 84b0ec68b..7fe4e69b9 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobRequest.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/BlobRequest.java @@ -373,7 +373,7 @@ public static HttpURLConnection deleteBlob(final URI uri, final BlobRequestOptio break; case INCLUDE_SNAPSHOTS: request.setRequestProperty(Constants.HeaderConstants.DELETE_SNAPSHOT_HEADER, - BlobConstants.INCLUDE_SNAPSHOTS_VALUE); + HeaderConstants.INCLUDE_SNAPSHOTS_VALUE); break; case DELETE_SNAPSHOTS_ONLY: request.setRequestProperty(Constants.HeaderConstants.DELETE_SNAPSHOT_HEADER, diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/CloudBlob.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/CloudBlob.java index 4992d89cf..9ab237434 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/CloudBlob.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/CloudBlob.java @@ -1354,18 +1354,19 @@ public Integer preProcessResponse(CloudBlob blob, CloudBlobClient client, Operat final BlobAttributes retrievedAttributes = BlobResponse.getBlobAttributes(this.getConnection(), blob.getStorageUri(), blob.snapshotID); - if (!options.getDisableContentMD5Validation() && options.getUseTransactionalContentMD5() - && Utility.isNullOrEmpty(retrievedAttributes.getProperties().getContentMD5())) { - throw new StorageException(StorageErrorCodeStrings.MISSING_MD5_HEADER, SR.MISSING_MD5, - Constants.HeaderConstants.HTTP_UNUSED_306, null, null); - } - blob.properties = retrievedAttributes.getProperties(); blob.metadata = retrievedAttributes.getMetadata(); // Need to store the Content MD5 in case we fail part way through. // We would still need to verify the entire range. String contentMD5 = this.getConnection().getHeaderField(Constants.HeaderConstants.CONTENT_MD5); + + if (!options.getDisableContentMD5Validation() && options.getUseTransactionalContentMD5() + && Utility.isNullOrEmpty(contentMD5)) { + throw new StorageException(StorageErrorCodeStrings.MISSING_MD5_HEADER, SR.MISSING_MD5, + Constants.HeaderConstants.HTTP_UNUSED_306, null, null); + } + this.setContentMD5(contentMD5); this.setLockedETag(blob.properties.getEtag()); this.setArePropertiesPopulated(true); diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/CloudPageBlob.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/CloudPageBlob.java index 79f612613..53863bed5 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/CloudPageBlob.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/blob/CloudPageBlob.java @@ -832,8 +832,7 @@ public BlobOutputStream openWriteExisting() throws StorageException { @DoesServiceRequest public BlobOutputStream openWriteExisting(AccessCondition accessCondition, BlobRequestOptions options, OperationContext opContext) throws StorageException { - return this - .openOutputStreamInternal(null /* length */, null /* accessCondition */, null /* options */, null /* opContext */); + return this.openOutputStreamInternal(null /* length */, accessCondition, options, opContext); } /** diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java index 976fe847e..32f43bcf6 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java @@ -115,11 +115,13 @@ public static RESULT_TYPE executeWithRet currResult.setStartDate(new Date()); Logger.info(opContext, LogConstants.GET_RESPONSE); + try { + currResult.setStatusCode(request.getResponseCode()); + currResult.setStatusMessage(request.getResponseMessage()); + } finally { + currResult.setStopDate(new Date()); + } - currResult.setStatusCode(request.getResponseCode()); - currResult.setStatusMessage(request.getResponseMessage()); - - currResult.setStopDate(new Date()); currResult.setServiceRequestID(BaseResponse.getRequestId(request)); currResult.setEtag(BaseResponse.getEtag(request)); currResult.setRequestDate(BaseResponse.getDate(request)); diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/core/SR.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/core/SR.java index 43973d90a..086d6e6dc 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/core/SR.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/core/SR.java @@ -92,7 +92,7 @@ public class SR { public static final String INVALID_DATE_STRING = "Invalid Date String: %s."; public static final String INVALID_EDMTYPE_VALUE = "Invalid value '%s' for EdmType."; public static final String INVALID_ENCRYPTION_ALGORITHM = "Invalid Encryption Algorithm found on the resource. This version of the client library does not support the specified encryption algorithm."; - public static final String INVALID_FILE_LENGTH = "File length must be greater than 0 bytes."; + public static final String INVALID_FILE_LENGTH = "File length must be greater than or equal to 0 bytes."; public static final String INVALID_GEO_REPLICATION_STATUS = "Null or Invalid geo-replication status in response: %s."; public static final String INVALID_IP_ADDRESS = "Error when parsing IPv4 address: IP address '%s' is invalid."; public static final String INVALID_KEY = "Storage Key is not a valid base64 encoded string."; @@ -103,6 +103,7 @@ public class SR { public static final String INVALID_MIME_RESPONSE = "Invalid MIME response received."; public static final String INVALID_NUMBER_OF_BYTES_IN_THE_BUFFER = "Page data must be a multiple of 512 bytes. Buffer currently contains %d bytes."; public static final String INVALID_OPERATION_FOR_A_SNAPSHOT = "Cannot perform this operation on a blob representing a snapshot."; + public static final String INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT = "Cannot perform this operation on a share representing a snapshot."; public static final String INVALID_PAGE_BLOB_LENGTH = "Page blob length must be multiple of 512."; public static final String INVALID_PAGE_START_OFFSET = "Page start offset must be multiple of 512."; public static final String INVALID_RANGE_CONTENT_MD5_HEADER = "Cannot specify x-ms-range-get-content-md5 header on ranges larger than 4 MB. Either use a BlobReadStream via openRead, or disable TransactionalMD5 via the BlobRequestOptions."; diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/core/SharedAccessSignatureHelper.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/core/SharedAccessSignatureHelper.java index af91d35a0..3826450a8 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/core/SharedAccessSignatureHelper.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/core/SharedAccessSignatureHelper.java @@ -418,7 +418,7 @@ public static StorageCredentialsSharedAccessSignature parseQuery(final StorageUr */ public static StorageCredentialsSharedAccessSignature parseQuery(final HashMap queryParams) throws StorageException { - + boolean sasParameterFound = false; List removeList = new ArrayList(); for (final Entry entry : queryParams.entrySet()) { @@ -434,9 +434,11 @@ public static StorageCredentialsSharedAccessSignature parseQuery(final HashMapCloudFile class using the specified absolute URI * and credentials. @@ -154,8 +154,9 @@ public CloudFile(final StorageUri fileAbsoluteUri) throws StorageException, URIS * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ - public CloudFile(final URI fileAbsoluteUri, final StorageCredentials credentials) throws StorageException { + public CloudFile(final URI fileAbsoluteUri, final StorageCredentials credentials) throws StorageException, URISyntaxException { this(new StorageUri(fileAbsoluteUri), credentials); } @@ -170,8 +171,9 @@ public CloudFile(final URI fileAbsoluteUri, final StorageCredentials credentials * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ - public CloudFile(final StorageUri fileAbsoluteUri, final StorageCredentials credentials) throws StorageException { + public CloudFile(final StorageUri fileAbsoluteUri, final StorageCredentials credentials) throws StorageException, URISyntaxException { this.parseQueryAndVerify(fileAbsoluteUri, credentials); } @@ -229,9 +231,10 @@ protected CloudFile(final StorageUri uri, final String fileName, final CloudFile * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public final void abortCopy(final String copyId) throws StorageException { + public final void abortCopy(final String copyId) throws StorageException, URISyntaxException { this.abortCopy(copyId, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -253,14 +256,17 @@ public final void abortCopy(final String copyId) throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public final void abortCopy(final String copyId, final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException { + OperationContext opContext) throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -426,9 +432,10 @@ public final String startCopy(final CloudFile sourceFile, final AccessCondition * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public final String startCopy(final URI source) throws StorageException { + public final String startCopy(final URI source) throws StorageException, URISyntaxException { return this.startCopy(source, null /* sourceAccessCondition */, null /* destinationAccessCondition */, null /* options */, null /* opContext */); } @@ -456,16 +463,19 @@ public final String startCopy(final URI source) throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException * */ @DoesServiceRequest public final String startCopy(final URI source, final AccessCondition sourceAccessCondition, final AccessCondition destinationAccessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException { + throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -534,9 +544,10 @@ public String preProcessResponse(CloudFile file, CloudFileClient client, Operati * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public void clearRange(final long offset, final long length) throws StorageException { + public void clearRange(final long offset, final long length) throws StorageException, URISyntaxException { this.clearRange(offset, length, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -563,14 +574,17 @@ public void clearRange(final long offset, final long length) throws StorageExcep * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public void clearRange(final long offset, final long length, final AccessCondition accessCondition, - FileRequestOptions options, OperationContext opContext) throws StorageException { + FileRequestOptions options, OperationContext opContext) throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); final FileRange range = new FileRange(offset, offset + length - 1); @@ -587,9 +601,10 @@ public void clearRange(final long offset, final long length, final AccessConditi * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public void create(final long size) throws StorageException { + public void create(final long size) throws StorageException, URISyntaxException { this.create(size, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -612,15 +627,18 @@ public void create(final long size) throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public void create(final long size, final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException { + OperationContext opContext) throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); ExecutionEngine.executeWithRetry(this.fileServiceClient, this, this.createImpl(size, accessCondition, options), @@ -672,9 +690,10 @@ public Void preProcessResponse(CloudFile file, CloudFileClient client, Operation * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public final void delete() throws StorageException { + public final void delete() throws StorageException, URISyntaxException { this.delete(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -694,14 +713,17 @@ public final void delete() throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public final void delete(final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException { + OperationContext opContext) throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -716,10 +738,11 @@ public final void delete(final AccessCondition accessCondition, FileRequestOptio * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException * */ @DoesServiceRequest - public final boolean deleteIfExists() throws StorageException { + public final boolean deleteIfExists() throws StorageException, URISyntaxException { return this.deleteIfExists(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -741,11 +764,13 @@ public final boolean deleteIfExists() throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public final boolean deleteIfExists(final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException { + OperationContext opContext) throws StorageException, URISyntaxException { options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); + this.getShare().assertNoSnapshot(); boolean exists = this.exists(true, accessCondition, options, opContext); if (exists) { @@ -1264,7 +1289,7 @@ public void setRequestLocationMode() { public HttpURLConnection buildRequest(CloudFileClient client, CloudFile file, OperationContext context) throws Exception { return FileRequest.getFileRanges(file.getTransformedAddress(context).getUri(this.getCurrentLocation()), - options, context, accessCondition); + options, context, accessCondition, file.getShare().snapshotID); } @Override @@ -1331,7 +1356,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFile file, Op // : accessCondition; return FileRequest.getFile(file.getTransformedAddress(context).getUri(this.getCurrentLocation()), - options, context, accessCondition, this.getOffset(), this.getLength(), + options, context, accessCondition, file.getShare().snapshotID, this.getOffset(), this.getLength(), (options.getUseTransactionalContentMD5() && !this.getArePropertiesPopulated())); } @@ -1354,12 +1379,6 @@ public Integer preProcessResponse(CloudFile file, CloudFileClient client, Operat final FileAttributes retrievedAttributes = FileResponse.getFileAttributes(this.getConnection(), file.getStorageUri()); - if (!options.getDisableContentMD5Validation() && options.getUseTransactionalContentMD5() - && Utility.isNullOrEmpty(retrievedAttributes.getProperties().getContentMD5())) { - throw new StorageException(StorageErrorCodeStrings.MISSING_MD5_HEADER, SR.MISSING_MD5, - Constants.HeaderConstants.HTTP_UNUSED_306, null, null); - } - file.properties = retrievedAttributes.getProperties(); file.metadata = retrievedAttributes.getMetadata(); @@ -1367,6 +1386,12 @@ public Integer preProcessResponse(CloudFile file, CloudFileClient client, Operat // We would still need to verify the entire range. this.setContentMD5(this.getConnection().getHeaderField(Constants.HeaderConstants.CONTENT_MD5)); + if (!options.getDisableContentMD5Validation() && options.getUseTransactionalContentMD5() + && Utility.isNullOrEmpty(this.getContentMD5())) { + throw new StorageException(StorageErrorCodeStrings.MISSING_MD5_HEADER, SR.MISSING_MD5, + Constants.HeaderConstants.HTTP_UNUSED_306, null, null); + } + this.setLockedETag(file.properties.getEtag()); this.setArePropertiesPopulated(true); } @@ -1506,7 +1531,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFile file, Op throws Exception { return FileRequest.getFileProperties( file.getTransformedAddress(context).getUri(this.getCurrentLocation()), - options, context, accessCondition); + options, context, accessCondition, file.getShare().snapshotID); } @Override @@ -1603,7 +1628,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFile file, Op throws Exception { return FileRequest.getFileProperties( file.getTransformedAddress(context).getUri(this.getCurrentLocation()), - options, context, accessCondition); + options, context, accessCondition, file.getShare().snapshotID); } @Override @@ -1825,9 +1850,10 @@ public final FileInputStream openRead(final AccessCondition accessCondition, Fil * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public FileOutputStream openWriteExisting() throws StorageException { + public FileOutputStream openWriteExisting() throws StorageException, URISyntaxException { return this .openOutputStreamInternal(null /* length */, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -1851,12 +1877,12 @@ public FileOutputStream openWriteExisting() throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public FileOutputStream openWriteExisting(AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException { - return this - .openOutputStreamInternal(null /* length */, null /* accessCondition */, null /* options */, null /* opContext */); + OperationContext opContext) throws StorageException, URISyntaxException { + return this.openOutputStreamInternal(null /* length */, accessCondition, options, opContext); } /** @@ -1874,9 +1900,10 @@ public FileOutputStream openWriteExisting(AccessCondition accessCondition, FileR * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public FileOutputStream openWriteNew(final long length) throws StorageException { + public FileOutputStream openWriteNew(final long length) throws StorageException, URISyntaxException { return this .openOutputStreamInternal(length, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -1906,10 +1933,11 @@ public FileOutputStream openWriteNew(final long length) throws StorageException * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public FileOutputStream openWriteNew(final long length, AccessCondition accessCondition, - FileRequestOptions options, OperationContext opContext) throws StorageException { + FileRequestOptions options, OperationContext opContext) throws StorageException, URISyntaxException { return openOutputStreamInternal(length, accessCondition, options, opContext); } @@ -1936,23 +1964,26 @@ public FileOutputStream openWriteNew(final long length, AccessCondition accessCo * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ private FileOutputStream openOutputStreamInternal(Long length, AccessCondition accessCondition, - FileRequestOptions options, OperationContext opContext) throws StorageException { + FileRequestOptions options, OperationContext opContext) throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient, false /* setStartTime */); if (length != null) { + this.create(length, accessCondition, options, opContext); + } + else { if (options.getStoreFileContentMD5()) { throw new IllegalArgumentException(SR.FILE_MD5_NOT_POSSIBLE); } - this.create(length, accessCondition, options, opContext); - } - else { this.downloadAttributes(accessCondition, options, opContext); length = this.getProperties().getLength(); } @@ -1977,9 +2008,10 @@ private FileOutputStream openOutputStreamInternal(Long length, AccessCondition a * @throws StorageException * If a storage service error occurred. * @throws IOException + * @throws URISyntaxException */ public void uploadFromByteArray(final byte[] buffer, final int offset, final int length) throws StorageException, - IOException { + IOException, URISyntaxException { uploadFromByteArray(buffer, offset, length, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2006,10 +2038,11 @@ public void uploadFromByteArray(final byte[] buffer, final int offset, final int * @throws StorageException * If a storage service error occurred. * @throws IOException + * @throws URISyntaxException */ public void uploadFromByteArray(final byte[] buffer, final int offset, final int length, final AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException, IOException { + throws StorageException, IOException, URISyntaxException { ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer, offset, length); this.upload(inputStream, length, accessCondition, options, opContext); inputStream.close(); @@ -2024,8 +2057,9 @@ public void uploadFromByteArray(final byte[] buffer, final int offset, final int * @throws StorageException * If a storage service error occurred. * @throws IOException + * @throws URISyntaxException */ - public void uploadFromFile(final String path) throws StorageException, IOException { + public void uploadFromFile(final String path) throws StorageException, IOException, URISyntaxException { uploadFromFile(path, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2048,9 +2082,10 @@ public void uploadFromFile(final String path) throws StorageException, IOExcepti * @throws StorageException * If a storage service error occurred. * @throws IOException + * @throws URISyntaxException */ public void uploadFromFile(final String path, final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, IOException { + OperationContext opContext) throws StorageException, IOException, URISyntaxException { File file = new File(path); long fileLength = file.length(); InputStream inputStream = new BufferedInputStream(new java.io.FileInputStream(file)); @@ -2068,8 +2103,9 @@ public void uploadFromFile(final String path, final AccessCondition accessCondit * @throws StorageException * If a storage service error occurred. * @throws IOException + * @throws URISyntaxException */ - public void uploadText(final String content) throws StorageException, IOException { + public void uploadText(final String content) throws StorageException, IOException, URISyntaxException { this.uploadText(content, null /* charsetName */, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2096,9 +2132,10 @@ public void uploadText(final String content) throws StorageException, IOExceptio * @throws StorageException * If a storage service error occurred. * @throws IOException + * @throws URISyntaxException */ public void uploadText(final String content, final String charsetName, final AccessCondition accessCondition, - FileRequestOptions options, OperationContext opContext) throws StorageException, IOException { + FileRequestOptions options, OperationContext opContext) throws StorageException, IOException, URISyntaxException { byte[] bytes = (charsetName == null) ? content.getBytes() : content.getBytes(charsetName); this.uploadFromByteArray(bytes, 0, bytes.length, accessCondition, options, opContext); } @@ -2118,10 +2155,11 @@ public void uploadText(final String content, final String charsetName, final Acc * If an I/O exception occurred. * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public void uploadRange(final InputStream sourceStream, final long offset, final long length) - throws StorageException, IOException { + throws StorageException, IOException, URISyntaxException { this.uploadRange(sourceStream, offset, length, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2150,15 +2188,18 @@ public void uploadRange(final InputStream sourceStream, final long offset, final * If an I/O exception occurred. * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public void uploadRange(final InputStream sourceStream, final long offset, final long length, final AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException, IOException { + throws StorageException, IOException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); final FileRange range = new FileRange(offset, offset + length - 1); @@ -2286,9 +2327,10 @@ public Void preProcessResponse(CloudFile file, CloudFileClient client, Operation * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public final void uploadMetadata() throws StorageException { + public final void uploadMetadata() throws StorageException, URISyntaxException { this.uploadMetadata(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2312,15 +2354,18 @@ public final void uploadMetadata() throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public final void uploadMetadata(final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException { + OperationContext opContext) throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -2376,9 +2421,10 @@ public Void preProcessResponse(CloudFile file, CloudFileClient client, Operation * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public final void uploadProperties() throws StorageException { + public final void uploadProperties() throws StorageException, URISyntaxException { this.uploadProperties(null /* accessCondition */, null /* options */, null /*opContext */); } @@ -2401,14 +2447,17 @@ public final void uploadProperties() throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public final void uploadProperties(final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException { + OperationContext opContext) throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -2460,8 +2509,9 @@ public Void preProcessResponse(CloudFile file, CloudFileClient client, Operation * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ - public void resize(long size) throws StorageException { + public void resize(long size) throws StorageException, URISyntaxException { this.resize(size, null /* accessCondition */, null /* options */, null /* operationContext */); } @@ -2483,13 +2533,16 @@ public void resize(long size) throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ public void resize(long size, AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException { + OperationContext opContext) throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -2544,9 +2597,10 @@ public Void preProcessResponse(CloudFile file, CloudFileClient client, Operation * If an I/O exception occurred. * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public void upload(final InputStream sourceStream, final long length) throws StorageException, IOException { + public void upload(final InputStream sourceStream, final long length) throws StorageException, IOException, URISyntaxException { this.upload(sourceStream, length, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2557,8 +2611,8 @@ public void upload(final InputStream sourceStream, final long length) throws Sto * @param sourceStream * An {@link InputStream} object to read from. * @param length - * A long which represents the length, in bytes, of the stream data. This must be great than - * zero. + * A long which represents the length, in bytes, of the stream data. This must be greater than + * or equal to zero. * @param accessCondition * An {@link AccessCondition} object which represents the access conditions for the file. * @param options @@ -2574,17 +2628,20 @@ public void upload(final InputStream sourceStream, final long length) throws Sto * If an I/O exception occurred. * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public void upload(final InputStream sourceStream, final long length, final AccessCondition accessCondition, - FileRequestOptions options, OperationContext opContext) throws StorageException, IOException { + FileRequestOptions options, OperationContext opContext) throws StorageException, IOException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); - if (length <= 0) { + if (length < 0) { throw new IllegalArgumentException(SR.INVALID_FILE_LENGTH); } @@ -2670,9 +2727,10 @@ protected static String getParentNameFromURI(final StorageUri resourceAddress, f * A {@link StorageCredentials} object used to authenticate access. * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCredentials credentials) - throws StorageException { + throws StorageException, URISyntaxException { Utility.assertNotNull("completeUri", completeUri); if (!completeUri.isAbsolute()) { @@ -2680,7 +2738,7 @@ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCred } this.storageUri = PathUtility.stripURIQueryAndFragment(completeUri); - + final StorageCredentialsSharedAccessSignature parsedCredentials = SharedAccessSignatureHelper.parseQuery(completeUri); @@ -2697,6 +2755,13 @@ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCred catch (final URISyntaxException e) { throw Utility.generateNewUnexpectedStorageException(e); } + + final HashMap queryParameters = PathUtility.parseQueryString(completeUri.getQuery()); + + final String[] snapshotIDs = queryParameters.get(Constants.QueryConstants.SHARE_SNAPSHOT); + if (snapshotIDs != null && snapshotIDs.length > 0) { + this.getShare().snapshotID = snapshotIDs[0]; + } } protected void updateEtagAndLastModifiedFromResponse(HttpURLConnection request) { @@ -2733,7 +2798,8 @@ public final CloudFileShare getShare() throws StorageException, URISyntaxExcepti if (this.share == null) { final StorageUri shareUri = PathUtility.getShareURI(this.getStorageUri(), this.fileServiceClient.isUsePathStyleUris()); - this.share = new CloudFileShare(shareUri, this.fileServiceClient.getCredentials()); + + this.share = new CloudFileShare(shareUri, this.fileServiceClient.getCredentials()/*, null*/); } return this.share; diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileClient.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileClient.java index f5bac5295..409d4ff27 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileClient.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileClient.java @@ -17,6 +17,7 @@ import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; +import java.util.EnumSet; import com.microsoft.azure.storage.DoesServiceRequest; import com.microsoft.azure.storage.OperationContext; @@ -100,7 +101,29 @@ public CloudFileClient(StorageUri storageUri, StorageCredentials credentials) { */ public CloudFileShare getShareReference(final String shareName) throws URISyntaxException, StorageException { Utility.assertNotNullOrEmpty("shareName", shareName); - return new CloudFileShare(shareName, this); + return this.getShareReference(shareName, null); + } + + /** + * Gets a {@link CloudFileShare} object with the specified name. + * + * @param shareName + * The name of the share, which must adhere to share naming rules. The share name should not + * include any path separator characters (/). + * Share names must be lowercase, between 3-63 characters long and must start with a letter or + * number. Share names may contain only letters, numbers, and the dash (-) character. + * @param snapshotID + * A String that represents the snapshot ID of the share. + * @return A reference to a {@link CloudFileShare} object. + * @throws StorageException + * @throws URISyntaxException + * + * @see Naming and Referencing Shares, + * Directories, Files, and Metadata + */ + protected CloudFileShare getShareReference(final String shareName, String snapshotID) throws URISyntaxException, StorageException { + Utility.assertNotNullOrEmpty("shareName", shareName); + return new CloudFileShare(shareName, snapshotID, this); } /** @@ -197,7 +220,7 @@ public ResultSegment listSharesSegmented(final String prefix) th * @param prefix * A String that represents the prefix of the share name. * @param detailsIncluded - * A {@link ShareListingDetails} value that indicates whether share metadata will be returned. + * A {@link ShareListingDetails} value that indicates whether share metadata will be returned. * @param maxResults * The maximum number of results to retrieve. If null or greater * than 5000, the server will return up to 5,000 items. Must be at least 1. @@ -271,7 +294,7 @@ private Iterable listSharesWithPrefix(final String prefix, * @param prefix * A String that represents the prefix of the share name. * @param detailsIncluded - * A {@link FileListingDetails} value that indicates whether share metadata will be returned. + * A {@link ShareListingDetails} value that indicates whether share metadata will be returned. * @param maxResults * The maximum number of results to retrieve. If null or greater * than 5000, the server will return up to 5,000 items. Must be at least 1. diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileDirectory.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileDirectory.java index a47944635..fcb275f32 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileDirectory.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileDirectory.java @@ -94,8 +94,9 @@ public final class CloudFileDirectory implements ListFileItem { * @param directoryAbsoluteUri * A {@link URI} that represents the file directory's address. * @throws StorageException + * @throws URISyntaxException */ - public CloudFileDirectory(final URI directoryAbsoluteUri) throws StorageException { + public CloudFileDirectory(final URI directoryAbsoluteUri) throws StorageException, URISyntaxException { this(new StorageUri(directoryAbsoluteUri)); } @@ -105,8 +106,9 @@ public CloudFileDirectory(final URI directoryAbsoluteUri) throws StorageExceptio * @param directoryAbsoluteUri * A {@link StorageUri} that represents the file directory's address. * @throws StorageException + * @throws URISyntaxException */ - public CloudFileDirectory(final StorageUri directoryAbsoluteUri) throws StorageException { + public CloudFileDirectory(final StorageUri directoryAbsoluteUri) throws StorageException, URISyntaxException { this(directoryAbsoluteUri, (StorageCredentials) null); } @@ -119,9 +121,10 @@ public CloudFileDirectory(final StorageUri directoryAbsoluteUri) throws StorageE * @param credentials * A {@link StorageCredentials} object used to authenticate access. * @throws StorageException + * @throws URISyntaxException */ public CloudFileDirectory(final URI directoryAbsoluteUri, final StorageCredentials credentials) - throws StorageException { + throws StorageException, URISyntaxException { this(new StorageUri(directoryAbsoluteUri), credentials); } @@ -134,9 +137,10 @@ public CloudFileDirectory(final URI directoryAbsoluteUri, final StorageCredentia * @param credentials * A {@link StorageCredentials} object used to authenticate access. * @throws StorageException + * @throws URISyntaxException */ public CloudFileDirectory(final StorageUri directoryAbsoluteUri, final StorageCredentials credentials) - throws StorageException { + throws StorageException, URISyntaxException { this.parseQueryAndVerify(directoryAbsoluteUri, credentials); } @@ -167,9 +171,10 @@ protected CloudFileDirectory(final StorageUri uri, final String directoryName, f * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public void create() throws StorageException { + public void create() throws StorageException, URISyntaxException { this.create(null /* options */, null /* opContext */); } @@ -187,13 +192,16 @@ public void create() throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public void create(FileRequestOptions options, OperationContext opContext) throws StorageException { + public void create(FileRequestOptions options, OperationContext opContext) throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -250,9 +258,10 @@ public Void preProcessResponse(CloudFileDirectory directory, CloudFileClient cli * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public boolean createIfNotExists() throws StorageException { + public boolean createIfNotExists() throws StorageException, URISyntaxException { return this.createIfNotExists(null /* options */, null /* opContext */); } @@ -272,11 +281,14 @@ public boolean createIfNotExists() throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public boolean createIfNotExists(FileRequestOptions options, OperationContext opContext) throws StorageException { + public boolean createIfNotExists(FileRequestOptions options, OperationContext opContext) throws StorageException, URISyntaxException { options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); + this.getShare().assertNoSnapshot(); + boolean exists = this.exists(true /* primaryOnly */, null /* accessCondition */, options, opContext); if (exists) { return false; @@ -303,9 +315,10 @@ public boolean createIfNotExists(FileRequestOptions options, OperationContext op * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public void delete() throws StorageException { + public void delete() throws StorageException, URISyntaxException { this.delete(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -325,14 +338,17 @@ public void delete() throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public void delete(AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException { + throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -378,9 +394,10 @@ public Void preProcessResponse(CloudFileDirectory directory, CloudFileClient cli * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public boolean deleteIfExists() throws StorageException { + public boolean deleteIfExists() throws StorageException, URISyntaxException { return this.deleteIfExists(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -402,10 +419,11 @@ public boolean deleteIfExists() throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public boolean deleteIfExists(AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException { + OperationContext opContext) throws StorageException, URISyntaxException { options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); boolean exists = this.exists(true /* primaryOnly */, accessCondition, options, opContext); @@ -498,7 +516,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFileDirectory OperationContext context) throws Exception { return FileRequest.getDirectoryProperties( directory.getTransformedAddress().getUri(this.getCurrentLocation()), options, context, - accessCondition); + accessCondition, directory.getShare().snapshotID); } @Override @@ -512,6 +530,12 @@ public Boolean preProcessResponse(CloudFileDirectory directory, CloudFileClient OperationContext context) throws Exception { if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_OK) { directory.updatePropertiesFromResponse(this.getConnection()); +// // Set properties +// final FileDirectoryAttributes attributes = +// FileResponse.getFileDirectoryAttributes(this.getConnection(), client.isUsePathStyleUris()); +// directory.setMetadata(attributes.getMetadata()); +// directory.setProperties(attributes.getProperties()); + return Boolean.valueOf(true); } else if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) { @@ -546,9 +570,10 @@ private void updatePropertiesFromResponse(HttpURLConnection request) { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest - public void uploadMetadata() throws StorageException { + public void uploadMetadata() throws StorageException, URISyntaxException { this.uploadMetadata(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -568,14 +593,17 @@ public void uploadMetadata() throws StorageException { * * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ @DoesServiceRequest public void uploadMetadata(AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException { + throws StorageException, URISyntaxException { if (opContext == null) { opContext = new OperationContext(); } + this.getShare().assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -679,7 +707,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFileDirectory OperationContext context) throws Exception { return FileRequest.getDirectoryProperties( directory.getTransformedAddress().getUri(this.getCurrentLocation()), options, context, - accessCondition); + accessCondition, directory.getShare().snapshotID); } @Override @@ -900,7 +928,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFileDirectory .getNextMarker() : null); return FileRequest.listFilesAndDirectories( directory.getTransformedAddress().getUri(this.getCurrentLocation()), - options, context, listingContext); + options, context, listingContext, directory.getShare().snapshotID); } @Override @@ -1058,6 +1086,7 @@ public CloudFileDirectory getParent() throws URISyntaxException, StorageExceptio if (parentName != null) { StorageUri parentURI = PathUtility.appendPathToUri(this.getShare().getStorageUri(), parentName); + this.parent = new CloudFileDirectory(parentURI, this.getServiceClient().getCredentials()); } } @@ -1135,9 +1164,10 @@ protected void setStorageUri(final StorageUri storageUri) { * A {@link StorageCredentials} object used to authenticate access. * @throws StorageException * If a storage service error occurred. + * @throws URISyntaxException */ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCredentials credentials) - throws StorageException { + throws StorageException, URISyntaxException { Utility.assertNotNull("completeUri", completeUri); if (!completeUri.isAbsolute()) { @@ -1145,7 +1175,7 @@ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCred } this.storageUri = PathUtility.stripURIQueryAndFragment(completeUri); - + final StorageCredentialsSharedAccessSignature parsedCredentials = SharedAccessSignatureHelper.parseQuery(completeUri); @@ -1162,6 +1192,13 @@ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCred catch (final URISyntaxException e) { throw Utility.generateNewUnexpectedStorageException(e); } + + final HashMap queryParameters = PathUtility.parseQueryString(completeUri.getQuery()); + + final String[] snapshotIDs = queryParameters.get(Constants.QueryConstants.SHARE_SNAPSHOT); + if (snapshotIDs != null && snapshotIDs.length > 0) { + this.getShare().snapshotID = snapshotIDs[0]; + } } /** diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java index 64fa0328a..d3d180261 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java @@ -78,6 +78,11 @@ public final class CloudFileShare { */ private StorageUri storageUri; + /** + * Holds the snapshot ID. + */ + String snapshotID; + /** * Holds a reference to the associated service client. */ @@ -92,6 +97,8 @@ public final class CloudFileShare { * The share name should not include any path separator characters (/). * Share names must be lowercase, between 3-63 characters long and must start with a letter or * number. Share names may contain only letters, numbers, and the dash (-) character. + * @param snapshotID + * A String that represents the snapshot version, if applicable. * @param client * A {@link CloudFileClient} object that represents the associated service client, and that specifies the * endpoint for the File service. @@ -104,13 +111,14 @@ public final class CloudFileShare { * @see Naming and Referencing Shares, * Directories, Files, and Metadata */ - protected CloudFileShare(final String shareName, final CloudFileClient client) throws URISyntaxException, + protected CloudFileShare(final String shareName, String snapshotID, final CloudFileClient client) throws URISyntaxException, StorageException { Utility.assertNotNull("client", client); Utility.assertNotNull("shareName", shareName); this.storageUri = PathUtility.appendPathToUri(client.getStorageUri(), shareName); this.name = shareName; + this.snapshotID = snapshotID; this.fileServiceClient = client; } @@ -139,7 +147,7 @@ public CloudFileShare(final URI uri) throws StorageException { public CloudFileShare(final StorageUri storageUri) throws StorageException { this(storageUri, (StorageCredentials) null); } - + /** * Creates an instance of the CloudFileShare class using the specified URI and credentials. * @@ -147,12 +155,14 @@ public CloudFileShare(final StorageUri storageUri) throws StorageException { * A java.net.URI object that represents the absolute URI of the share. * @param credentials * A {@link StorageCredentials} object used to authenticate access. + * @param snapshotID + * A String that represents the snapshot version, if applicable. * * @throws StorageException * If a storage service error occurred. */ - public CloudFileShare(final URI uri, final StorageCredentials credentials) throws StorageException { - this(new StorageUri(uri), credentials); + public CloudFileShare(final URI uri, final StorageCredentials credentials/*, String snapshotID*/) throws StorageException { + this(new StorageUri(uri), credentials /*, snapshotID*/); } /** @@ -162,12 +172,22 @@ public CloudFileShare(final URI uri, final StorageCredentials credentials) throw * A {@link StorageUri} object which represents the absolute StorageUri of the share. * @param credentials * A {@link StorageCredentials} object used to authenticate access. - * + * @param snapshotID + * A String that represents the snapshot version, if applicable. * @throws StorageException * If a storage service error occurred. */ - public CloudFileShare(final StorageUri storageUri, final StorageCredentials credentials) throws StorageException { + public CloudFileShare(final StorageUri storageUri, final StorageCredentials credentials/*, String snapshotID*/) throws StorageException { this.parseQueryAndVerify(storageUri, credentials); + +// if (snapshotID != null) { +// if (this.snapshotID != null) { +// throw new IllegalArgumentException(SR.SNAPSHOT_QUERY_OPTION_ALREADY_DEFINED); +// } +// else { +// this.snapshotID = snapshotID; +// } +// } } /** @@ -202,6 +222,11 @@ public void create(FileRequestOptions options, OperationContext opContext) throw opContext = new OperationContext(); } + assertNoSnapshot(); + if (this.properties != null && this.properties.getShareQuota() != null) { + Utility.assertInBounds("Share Quota", this.properties.getShareQuota(), 1, FileConstants.MAX_SHARE_QUOTA); + } + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -319,7 +344,7 @@ public boolean createIfNotExists(FileRequestOptions options, OperationContext op */ @DoesServiceRequest public void delete() throws StorageException { - this.delete(null /* accessCondition */, null /* options */, null /* opContext */); + this.delete(DeleteShareSnapshotsOption.NONE, null /* accessCondition */, null /* options */, null /* opContext */); } /** @@ -342,6 +367,36 @@ public void delete() throws StorageException { @DoesServiceRequest public void delete(AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) throws StorageException { + this.delete(DeleteShareSnapshotsOption.NONE, accessCondition, options, opContext); + } + + /** + * Deletes the share using the specified snapshot and request options, and operation context. + *

+ * A share that has snapshots cannot be deleted unless the snapshots are also deleted. If a share has snapshots, use + * the {@link DeleteShareSnapshotsOption#INCLUDE_SNAPSHOTS} value + * in the deleteSnapshotsOption parameter to include the snapshots when deleting the base share. + * + * @param deleteSnapshotsOption + * A {@link DeleteShareSnapshotsOption} object that indicates whether to delete only snapshots, or the share + * and its snapshots. + * @param accessCondition + * An {@link AccessCondition} object that represents the access conditions for the share. + * @param options + * A {@link FileRequestOptions} object that specifies any additional options for the request. Specifying + * null will use the default request options from the associated service client ( + * {@link CloudFileClient}). + * @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 + protected void delete(DeleteShareSnapshotsOption deleteSnapshotsOption, AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) + throws StorageException { if (opContext == null) { opContext = new OperationContext(); } @@ -349,12 +404,12 @@ public void delete(AccessCondition accessCondition, FileRequestOptions options, opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); - ExecutionEngine.executeWithRetry(this.fileServiceClient, this, deleteImpl(accessCondition, options), + ExecutionEngine.executeWithRetry(this.fileServiceClient, this, deleteImpl(deleteSnapshotsOption, accessCondition, options), options.getRetryPolicyFactory(), opContext); } private StorageRequest deleteImpl( - final AccessCondition accessCondition, final FileRequestOptions options) { + final DeleteShareSnapshotsOption deleteSnapshotsOption, final AccessCondition accessCondition, final FileRequestOptions options) { final StorageRequest putRequest = new StorageRequest(options, this.getStorageUri()) { @@ -363,7 +418,7 @@ private StorageRequest deleteImpl( public HttpURLConnection buildRequest( CloudFileClient client, CloudFileShare share, OperationContext context) throws Exception { return FileRequest.deleteShare( - share.getTransformedAddress().getPrimaryUri(), options, context, accessCondition); + share.getTransformedAddress().getPrimaryUri(), options, context, accessCondition, share.snapshotID, deleteSnapshotsOption); } @Override @@ -396,12 +451,13 @@ public Void preProcessResponse(CloudFileShare share, CloudFileClient client, Ope */ @DoesServiceRequest public boolean deleteIfExists() throws StorageException { - return this.deleteIfExists(null /* accessCondition */, null /* options */, null /* opContext */); + return this.deleteIfExists(DeleteShareSnapshotsOption.NONE, null /* accessCondition */, null /* options */, null /* opContext */); } - + /** * Deletes the share if it exists using the specified request options and operation context. * + * * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the share. * @param options @@ -421,12 +477,45 @@ public boolean deleteIfExists() throws StorageException { @DoesServiceRequest public boolean deleteIfExists(AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) throws StorageException { + return this.deleteIfExists(DeleteShareSnapshotsOption.NONE, accessCondition, options, opContext); + + } + + /** + * Deletes the share if it exists, using the specified snapshot and request options, and operation context. + *

+ * A share that has snapshots cannot be deleted unless the snapshots are also deleted. If a share has snapshots, use + * the {@link DeleteShareSnapshotsOption#INCLUDE_SNAPSHOTS} value + * in the deleteSnapshotsOption parameter to include the snapshots when deleting the base share. + * + * @param deleteSnapshotsOption + * A {@link DeleteShareSnapshotsOption} object that indicates whether to delete only snapshots, or the share + * and its snapshots. + * @param accessCondition + * An {@link AccessCondition} object that represents the access conditions for the share. + * @param options + * A {@link FileRequestOptions} object that specifies any additional options for the request. Specifying + * null will use the default request options from the associated service client ( + * {@link CloudFileClient}). + * @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 share existed and was deleted; otherwise, false. + * + * @throws StorageException + * If a storage service error occurred. + */ + @DoesServiceRequest + protected boolean deleteIfExists(DeleteShareSnapshotsOption deleteSnapshotsOption, AccessCondition accessCondition, FileRequestOptions options, + OperationContext opContext) throws StorageException { options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); boolean exists = this.exists(true /* primaryOnly */, accessCondition, options, opContext); if (exists) { try { - this.delete(accessCondition, options, opContext); + this.delete(deleteSnapshotsOption, accessCondition, options, opContext); return true; } catch (StorageException e) { @@ -501,7 +590,7 @@ public void setRequestLocationMode() { public HttpURLConnection buildRequest(CloudFileClient client, CloudFileShare share, OperationContext context) throws Exception { return FileRequest.getShareProperties(share.getTransformedAddress().getUri(this.getCurrentLocation()), - options, context, accessCondition); + options, context, accessCondition, share.snapshotID); } @Override @@ -569,6 +658,8 @@ public FileSharePermissions downloadPermissions(AccessCondition accessCondition, opContext = new OperationContext(); } + assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -628,6 +719,136 @@ public FileSharePermissions postProcessResponse(HttpURLConnection connection, return getRequest; } + /** + * Creates a snapshot of the share. + * + * @return A CloudFileShare object that represents the snapshot of the share. + * + * @throws StorageException + * If a storage service error occurred. + */ + @DoesServiceRequest + protected final CloudFileShare createSnapshot() throws StorageException { + return this + .createSnapshot(null /* metadata */, null /* accessCondition */, null /* options */, null /* opContext */); + } + + /** + * Creates a snapshot of the file share using the specified request options and operation context. + * + * @param accessCondition + * An {@link AccessCondition} object that represents the access conditions for the share. + * @param options + * A {@link FileRequestOptions} object that specifies any additional options for the request. Specifying + * null will use the default request options from the associated service client ( + * {@link CloudFileClient}). + * @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 CloudFileShare object that represents the snapshot of the file share. + * + * @throws StorageException + * If a storage service error occurred. + */ + @DoesServiceRequest + protected final CloudFileShare createSnapshot(final AccessCondition accessCondition, FileRequestOptions options, + OperationContext opContext) throws StorageException { + return this.createSnapshot(null /* metadata */, accessCondition, options, opContext); + } + + /** + * Creates a snapshot of the file share using the specified request options and operation context. + * + * @param metadata + * A collection of name-value pairs defining the metadata of the snapshot, or null. + * @param accessCondition + * An {@link AccessCondition} object that represents the access conditions for the file share. + * @param options + * A {@link FileRequestOptions} object that specifies any additional options for the request. Specifying + * null will use the default request options from the associated service client ( + * {@link CloudFileClient}). + * @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 CloudFileShare object that represents the snapshot of the file share. + * + * @throws StorageException + * If a storage service error occurred. + */ + @DoesServiceRequest + protected final CloudFileShare createSnapshot(final HashMap metadata, + final AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) + throws StorageException { + assertNoSnapshot(); + + if (opContext == null) { + opContext = new OperationContext(); + } + + opContext.initialize(); + options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); + + return ExecutionEngine + .executeWithRetry(this.fileServiceClient, this, + this.createSnapshotImpl(metadata, accessCondition, options), options.getRetryPolicyFactory(), + opContext); + } + + private StorageRequest createSnapshotImpl( + final HashMap metadata, final AccessCondition accessCondition, + final FileRequestOptions options) { + final StorageRequest putRequest = + new StorageRequest( + options, this.getStorageUri()) { + + @Override + public HttpURLConnection buildRequest(CloudFileClient client, CloudFileShare share, OperationContext context) + throws Exception { + return FileRequest.snapshotShare(share.getTransformedAddress().getUri(this.getCurrentLocation()), + options, context, accessCondition); + } + + @Override + public void setHeaders(HttpURLConnection connection, CloudFileShare share, OperationContext context) { + if (metadata != null) { + FileRequest.addMetadata(connection, metadata, context); + } + } + + @Override + public void signRequest(HttpURLConnection connection, CloudFileClient client, OperationContext context) + throws Exception { + StorageRequest.signBlobQueueAndFileRequest(connection, client, 0L, context); + } + + @Override + public CloudFileShare preProcessResponse(CloudFileShare share, CloudFileClient client, OperationContext context) + throws Exception { + if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { + this.setNonExceptionedRetryableFailure(true); + return null; + } + + final String snapshotTime = FileResponse.getSnapshotTime(this.getConnection()); + CloudFileShare snapshot = new CloudFileShare(share.getName(), snapshotTime, client); + snapshot.setProperties(new FileShareProperties(share.properties)); + + // use the specified metadata if not null : otherwise share's metadata + snapshot.setMetadata(metadata != null ? metadata : share.metadata); + + snapshot.updatePropertiesFromResponse(this.getConnection()); + + return snapshot; + } + }; + + return putRequest; + } + /** * Queries the service for this share's {@link ShareStats}. * @@ -664,6 +885,8 @@ public ShareStats getStats(FileRequestOptions options, OperationContext opContex opContext = new OperationContext(); } + assertNoSnapshot(); + opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -783,7 +1006,7 @@ public void setRequestLocationMode() { public HttpURLConnection buildRequest(CloudFileClient client, CloudFileShare share, OperationContext context) throws Exception { return FileRequest.getShareProperties(share.getTransformedAddress().getUri(this.getCurrentLocation()), - options, context, accessCondition); + options, context, accessCondition, share.snapshotID); } @Override @@ -797,6 +1020,11 @@ public Boolean preProcessResponse(CloudFileShare share, CloudFileClient client, throws Exception { if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_OK) { share.updatePropertiesFromResponse(this.getConnection()); +// final FileShareAttributes attributes = FileResponse.getFileShareAttributes(this.getConnection(), +// client.isUsePathStyleUris()); +// share.metadata = attributes.getMetadata(); +// share.properties = attributes.getProperties(); + return Boolean.valueOf(true); } else if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) { @@ -804,6 +1032,7 @@ else if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) { } else { this.setNonExceptionedRetryableFailure(true); + // return false instead of null to avoid SCA issues return false; } @@ -814,6 +1043,10 @@ else if (this.getResult().getStatusCode() == HttpURLConnection.HTTP_NOT_FOUND) { } private void updatePropertiesFromResponse(HttpURLConnection request) { + if (this.getProperties() == null) { + this.properties = new FileShareProperties(); + } + // ETag this.getProperties().setEtag(request.getHeaderField(Constants.HeaderConstants.ETAG)); @@ -826,6 +1059,15 @@ private void updatePropertiesFromResponse(HttpURLConnection request) { } } + /** + * Asserts that the share is not a snapshot. + */ + protected void assertNoSnapshot() { + if (isSnapshot()) { + throw new IllegalArgumentException(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT); + } + } + /** * Returns a shared access signature for the share. Note this does not contain the leading "?". * @@ -933,6 +1175,8 @@ public void uploadMetadata() throws StorageException { @DoesServiceRequest public void uploadMetadata(AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) throws StorageException { + assertNoSnapshot(); + if (opContext == null) { opContext = new OperationContext(); } @@ -1021,6 +1265,12 @@ public final void uploadProperties() throws StorageException { public final void uploadProperties( AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) throws StorageException { + assertNoSnapshot(); + + if (this.properties != null && this.properties.getShareQuota() != null) { + Utility.assertInBounds("Share Quota", this.properties.getShareQuota(), 1, FileConstants.MAX_SHARE_QUOTA); + } + if (opContext == null) { opContext = new OperationContext(); } @@ -1102,6 +1352,8 @@ public void uploadPermissions(final FileSharePermissions permissions) throws Sto @DoesServiceRequest public void uploadPermissions(final FileSharePermissions permissions, final AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) throws StorageException { + assertNoSnapshot(); + if (opContext == null) { opContext = new OperationContext(); } @@ -1201,7 +1453,14 @@ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCred } this.storageUri = PathUtility.stripURIQueryAndFragment(completeUri); - + + final HashMap queryParameters = PathUtility.parseQueryString(completeUri.getQuery()); + + final String[] snapshotIDs = queryParameters.get(Constants.QueryConstants.SHARE_SNAPSHOT); + if (snapshotIDs != null && snapshotIDs.length > 0) { + this.snapshotID = snapshotIDs[0]; + } + final StorageCredentialsSharedAccessSignature parsedCredentials = SharedAccessSignatureHelper.parseQuery(completeUri); @@ -1238,6 +1497,26 @@ public URI getUri() { return this.storageUri.getPrimaryUri(); } + /** + * Returns the snapshotID for this share. + * + * @return The snapshotID as a string for this share. + */ + protected final String getSnapshot() { + return this.snapshotID; + } + + /** + * Indicates whether this share is a snapshot. + * + * @return true if the share is a snapshot, otherwise false. + * + * @see DeleteSnapshotsOption + */ + protected final boolean isSnapshot() { + return this.snapshotID != null; + } + /** * Returns the list of URIs for all locations. * @@ -1247,6 +1526,24 @@ public StorageUri getStorageUri() { return this.storageUri; } + /** + * Returns the snapshot or shared access signature qualified URI for this share. + * + * @return A java.net.URI object that represents the snapshot or shared access signature. + * + * @throws StorageException + * If a storage service error occurred. + * @throws URISyntaxException + * If the resource URI is invalid. + */ + public final URI getQualifiedUri() throws URISyntaxException, StorageException { + if (this.isSnapshot()) { + return PathUtility.addToQuery(this.getUri(), String.format("sharesnapshot=%s", this.snapshotID)); + } + + return this.fileServiceClient.getCredentials().transformUri(this.getUri()); + } + /** * Returns the name of the share. * diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileOutputStream.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileOutputStream.java index f768db829..6d28da2a5 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileOutputStream.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileOutputStream.java @@ -19,6 +19,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.net.URISyntaxException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.concurrent.Callable; @@ -205,6 +206,8 @@ public void close() throws IOException { } catch (final StorageException e) { throw Utility.initIOException(e); + } catch (URISyntaxException e) { + throw Utility.initIOException(e); } } finally { @@ -227,9 +230,10 @@ public void close() throws IOException { * * @throws StorageException * An exception representing any error which occurred during the operation. + * @throws URISyntaxException */ @DoesServiceRequest - private void commit() throws StorageException { + private void commit() throws StorageException, URISyntaxException { if (this.options.getStoreFileContentMD5()) { this.parentFileRef.getProperties().setContentMD5(Base64.encode(this.md5Digest.digest())); } @@ -271,7 +275,7 @@ private synchronized void dispatchWrite(final int writeLength) throws IOExceptio worker = new Callable() { @Override - public Void call() { + public Void call() throws URISyntaxException { try { fileRef.uploadRange(bufferRef, opOffset, opWriteLength, FileOutputStream.this.accessCondition, FileOutputStream.this.options, FileOutputStream.this.opContext); diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileRequest.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileRequest.java index dc00aa6cc..092f4866a 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileRequest.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileRequest.java @@ -18,6 +18,7 @@ import java.net.HttpURLConnection; import java.net.URI; import java.net.URISyntaxException; +import java.util.EnumSet; import java.util.Map; import com.microsoft.azure.storage.AccessCondition; @@ -38,6 +39,8 @@ final class FileRequest { private static final String RANGE_LIST_QUERY_ELEMENT_NAME = "rangelist"; + private static final String SNAPSHOTS_QUERY_ELEMENT_NAME = "snapshots"; + /** * Generates a web request to abort a copy operation. * @@ -118,6 +121,23 @@ private static void addProperties(final HttpURLConnection request, FilePropertie BaseRequest.addOptionalHeader(request, FileConstants.CONTENT_TYPE_HEADER, properties.getContentType()); } + /** + * Adds the share snapshot if present. + * Only for listing files and directories which requires a different query param. + * + * @param builder + * a query builder. + * @param snapshotVersion + * the share snapshot version to the query builder. + * @throws StorageException + */ + public static void addShareSnapshot(final UriQueryBuilder builder, final String snapshotVersion) + throws StorageException { + if (snapshotVersion != null) { + builder.add(Constants.QueryConstants.SHARE_SNAPSHOT, snapshotVersion); + } + } + /** * Creates a request to copy a file, Sign with 0 length. * @@ -268,14 +288,27 @@ public static HttpURLConnection deleteFile(final URI uri, final FileRequestOptio * @throws IllegalArgumentException */ public static HttpURLConnection deleteShare(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, final AccessCondition accessCondition) throws IOException, - URISyntaxException, StorageException { + final OperationContext opContext, final AccessCondition accessCondition, String snapshotVersion, DeleteShareSnapshotsOption deleteSnapshotsOption) + throws IOException, URISyntaxException, StorageException { final UriQueryBuilder shareBuilder = getShareUriQueryBuilder(); + FileRequest.addShareSnapshot(shareBuilder, snapshotVersion); HttpURLConnection request = BaseRequest.delete(uri, fileOptions, shareBuilder, opContext); if (accessCondition != null) { accessCondition.applyConditionToRequest(request); } + switch (deleteSnapshotsOption) { + case NONE: + // nop + break; + case INCLUDE_SNAPSHOTS: + request.setRequestProperty(Constants.HeaderConstants.DELETE_SNAPSHOT_HEADER, + Constants.HeaderConstants.INCLUDE_SNAPSHOTS_VALUE); + break; + default: + break; + } + return request; } @@ -329,6 +362,8 @@ public static HttpURLConnection getAcl(final URI uri, final FileRequestOptions f * the operation. * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the file. + * @param snapshotVersion + * The snapshot version, if the share is a snapshot. * @param offset * The offset at which to begin returning content. * @param count @@ -345,7 +380,7 @@ public static HttpURLConnection getAcl(final URI uri, final FileRequestOptions f * @throws IllegalArgumentException */ public static HttpURLConnection getFile(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, final AccessCondition accessCondition, final Long offset, + final OperationContext opContext, final AccessCondition accessCondition, final String snapshotVersion, final Long offset, final Long count, boolean requestRangeContentMD5) throws IOException, URISyntaxException, StorageException { if (offset != null && requestRangeContentMD5) { @@ -354,6 +389,7 @@ public static HttpURLConnection getFile(final URI uri, final FileRequestOptions } final UriQueryBuilder builder = new UriQueryBuilder(); + FileRequest.addShareSnapshot(builder, snapshotVersion); final HttpURLConnection request = BaseRequest.createURLConnection(uri, fileOptions, builder, opContext); request.setRequestMethod(Constants.HTTP_GET); @@ -398,6 +434,8 @@ public static HttpURLConnection getFile(final URI uri, final FileRequestOptions * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the file. * @return a HttpURLConnection to use to perform the operation. + * @param snapshotVersion + * the snapshot version to the query builder. * @throws IOException * if there is an error opening the connection * @throws URISyntaxException @@ -407,10 +445,11 @@ public static HttpURLConnection getFile(final URI uri, final FileRequestOptions * @throws IllegalArgumentException */ public static HttpURLConnection getFileProperties(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, final AccessCondition accessCondition) throws StorageException, + final OperationContext opContext, final AccessCondition accessCondition, final String snapshotVersion) throws StorageException, IOException, URISyntaxException { final UriQueryBuilder builder = new UriQueryBuilder(); - return getProperties(uri, fileOptions, opContext, accessCondition, builder); + + return getProperties(uri, fileOptions, opContext, accessCondition, builder, snapshotVersion); } /** @@ -428,6 +467,8 @@ public static HttpURLConnection getFileProperties(final URI uri, final FileReque * the operation. * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the file. + * @param snapshotVersion + * the snapshot version to the query builder. * @return a HttpURLConnection to use to perform the operation. * @throws IOException * if there is an error opening the connection @@ -438,10 +479,11 @@ public static HttpURLConnection getFileProperties(final URI uri, final FileReque * @throws IllegalArgumentException */ public static HttpURLConnection getFileRanges(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, final AccessCondition accessCondition) throws StorageException, + final OperationContext opContext, final AccessCondition accessCondition, final String snapshotVersion) throws StorageException, IOException, URISyntaxException { final UriQueryBuilder builder = new UriQueryBuilder(); + addShareSnapshot(builder, snapshotVersion); builder.add(Constants.QueryConstants.COMPONENT, RANGE_LIST_QUERY_ELEMENT_NAME); final HttpURLConnection request = BaseRequest.createURLConnection(uri, fileOptions, builder, opContext); @@ -469,14 +511,17 @@ public static HttpURLConnection getFileRanges(final URI uri, final FileRequestOp * the operation. * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the share. + * @param snapshotVersion + * the snapshot version to the query builder. * @return a HttpURLConnection configured for the operation. * @throws StorageException * */ public static HttpURLConnection getShareProperties(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, AccessCondition accessCondition) throws IOException, URISyntaxException, + final OperationContext opContext, AccessCondition accessCondition, final String snapshotVersion) throws IOException, URISyntaxException, StorageException { final UriQueryBuilder shareBuilder = getShareUriQueryBuilder(); - return getProperties(uri, fileOptions, opContext, accessCondition, shareBuilder); + + return getProperties(uri, fileOptions, opContext, accessCondition, shareBuilder, snapshotVersion); } /** @@ -559,12 +604,16 @@ private static UriQueryBuilder getDirectoryUriQueryBuilder() throws StorageExcep * the operation. * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the share. + * @param snapshotVersion + * the snapshot version to the query builder. * @return a HttpURLConnection configured for the operation. * @throws StorageException * */ private static HttpURLConnection getProperties(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, AccessCondition accessCondition, final UriQueryBuilder builder) + final OperationContext opContext, AccessCondition accessCondition, final UriQueryBuilder builder, + String snapshotVersion) throws IOException, URISyntaxException, StorageException { + addShareSnapshot(builder, snapshotVersion); HttpURLConnection request = BaseRequest.getProperties(uri, fileOptions, builder, opContext); if (accessCondition != null) { @@ -591,7 +640,7 @@ private static HttpURLConnection getProperties(final URI uri, final FileRequestO * @param listingContext * A set of parameters for the listing operation. * @param detailsIncluded - * Additional details to return with the listing. + * Additional details to return with the listing. * @return a HttpURLConnection configured for the operation. * @throws IOException * @throws URISyntaxException @@ -601,9 +650,29 @@ private static HttpURLConnection getProperties(final URI uri, final FileRequestO public static HttpURLConnection listShares(final URI uri, final FileRequestOptions fileOptions, final OperationContext opContext, final ListingContext listingContext, final ShareListingDetails detailsIncluded) throws URISyntaxException, IOException, StorageException { - final UriQueryBuilder builder = BaseRequest.getListUriQueryBuilder(listingContext); +// if (detailsIncluded != null && detailsIncluded.size() > 0) { +// final StringBuilder sb = new StringBuilder(); +// boolean started = false; + +// if (detailsIncluded.contains(ShareListingDetails.SNAPSHOTS)) { +// started = true; +// sb.append(SNAPSHOTS_QUERY_ELEMENT_NAME); +// } + +// if (detailsIncluded.contains(ShareListingDetails.METADATA)) { +// if (started) +// { +// sb.append(","); +// } +// +// sb.append(Constants.QueryConstants.METADATA); +// } + +// builder.add(Constants.QueryConstants.INCLUDE, sb.toString()); +// } + if (detailsIncluded == ShareListingDetails.ALL || detailsIncluded == ShareListingDetails.METADATA) { builder.add(Constants.QueryConstants.INCLUDE, Constants.QueryConstants.METADATA); } @@ -741,14 +810,16 @@ public static HttpURLConnection deleteDirectory(final URI uri, final FileRequest * the operation. * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the directory. + * @param snapshotVersion + * the snapshot version to the query builder. * @return a HttpURLConnection configured for the operation. * @throws StorageException * */ public static HttpURLConnection getDirectoryProperties(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, AccessCondition accessCondition) throws IOException, URISyntaxException, + final OperationContext opContext, AccessCondition accessCondition, String snapshotVersion) throws IOException, URISyntaxException, StorageException { final UriQueryBuilder directoryBuilder = getDirectoryUriQueryBuilder(); - return getProperties(uri, fileOptions, opContext, accessCondition, directoryBuilder); + return getProperties(uri, fileOptions, opContext, accessCondition, directoryBuilder, snapshotVersion); } /** @@ -767,6 +838,8 @@ public static HttpURLConnection getDirectoryProperties(final URI uri, final File * the operation. * @param listingContext * A set of parameters for the listing operation. + * @param snapshotVersion + * the snapshot version to the query builder. * @return a HttpURLConnection configured for the operation. * @throws IOException * @throws URISyntaxException @@ -774,10 +847,11 @@ public static HttpURLConnection getDirectoryProperties(final URI uri, final File * @throws IllegalArgumentException */ public static HttpURLConnection listFilesAndDirectories(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, final ListingContext listingContext) throws URISyntaxException, + final OperationContext opContext, final ListingContext listingContext, String snapshotVersion) throws URISyntaxException, IOException, StorageException { final UriQueryBuilder builder = getDirectoryUriQueryBuilder(); + addShareSnapshot(builder, snapshotVersion); builder.add(Constants.QueryConstants.COMPONENT, Constants.QueryConstants.LIST); if (listingContext != null) { @@ -1099,6 +1173,49 @@ public static HttpURLConnection setFileMetadata(final URI uri, final FileRequest return setMetadata(uri, fileOptions, opContext, accessCondition, null); } + /** + * Constructs a HttpURLConnection to create a snapshot of the share. + * + * @param uri + * A java.net.URI object that specifies the absolute URI. + * @param fileOptions + * A {@link FileRequestOptions} object that specifies execution options such as retry policy and timeout + * settings for the operation. Specify null to use the request options specified on the + * {@link CloudFileClient}. + * @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. + * @param accessCondition + * An {@link AccessCondition} object that represents the access conditions for the share. + * @return a HttpURLConnection to use to perform the operation. + * @throws IOException + * if there is an error opening the connection + * @throws URISyntaxException + * if the resource URI is invalid + * @throws StorageException + * an exception representing any error which occurred during the operation. + * @throws IllegalArgumentException + */ + public static HttpURLConnection snapshotShare(final URI uri, final FileRequestOptions fileOptions, + final OperationContext opContext, final AccessCondition accessCondition) throws IOException, + URISyntaxException, StorageException { + final UriQueryBuilder builder = new UriQueryBuilder(); + builder.add(Constants.QueryConstants.RESOURCETYPE, "share"); + builder.add(Constants.QueryConstants.COMPONENT, Constants.QueryConstants.SNAPSHOT); + final HttpURLConnection request = BaseRequest.createURLConnection(uri, fileOptions, builder, opContext); + + request.setFixedLengthStreamingMode(0); + request.setDoOutput(true); + request.setRequestMethod(Constants.HTTP_PUT); + + if (accessCondition != null) { + accessCondition.applyConditionToRequest(request); + } + + return request; + } + /** * Constructs a HttpURLConnection to set the file's properties, Sign with zero length specified. * diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileResponse.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileResponse.java index 40a1c5166..14d7bcfcd 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileResponse.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileResponse.java @@ -205,6 +205,17 @@ static Integer parseShareQuota(final HttpURLConnection request) { return (shareQuota == -1) ? null : shareQuota; } + /** + * Gets the snapshot ID from the request header. + * + * @param request + * The response from server. + * @return the snapshot ID from the request header. + */ + public static String getSnapshotTime(final HttpURLConnection request) { + return request.getHeaderField(Constants.HeaderConstants.SNAPSHOT_ID_HEADER); + } + /** * Private Default Ctor */ diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileShareProperties.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileShareProperties.java index c5e29c6e3..e83408512 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileShareProperties.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileShareProperties.java @@ -17,7 +17,6 @@ import java.util.Date; import com.microsoft.azure.storage.AccessCondition; -import com.microsoft.azure.storage.core.Utility; /** * Represents the system properties for a share. @@ -39,6 +38,27 @@ public final class FileShareProperties { */ private Integer shareQuota; + /** + * Creates an instance of the FileShareProperties class. + */ + public FileShareProperties() { + } + + /** + * Creates an instance of the FileShareProperties class by copying values from another + * FileShareProperties instance. + * + * @param other + * A {@link FileShareProperties} object which represents the file share properties to copy. + */ + public FileShareProperties(final FileShareProperties other) { + if (other != null) { + this.setEtag(other.getEtag()); + this.setLastModified(other.getLastModified()); + this.setShareQuota(other.getShareQuota()); + } + } + /** * Gets the ETag value of the share. *

@@ -102,9 +122,6 @@ protected void setLastModified(final Date lastModified) { * the size of files stored on the share. */ public void setShareQuota(Integer shareQuota) { - if (shareQuota != null) { - Utility.assertInBounds("Share Quota", shareQuota, 1, FileConstants.MAX_SHARE_QUOTA); - } this.shareQuota = shareQuota; } } \ No newline at end of file diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListHandler.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListHandler.java index c73693da1..3d3b9b99f 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListHandler.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListHandler.java @@ -46,6 +46,7 @@ final class ShareListHandler extends DefaultHandler { private final ListResponse response = new ListResponse(); private FileShareAttributes attributes; private String shareName; + private String snapshotID; private ShareListHandler(CloudFileClient serviceClient) { this.serviceClient = serviceClient; @@ -77,6 +78,7 @@ public void startElement(String uri, String localName, String qName, Attributes if (FileConstants.SHARE_ELEMENT.equals(localName)) { this.shareName = Constants.EMPTY_STRING; + this.snapshotID = null; this.attributes = new FileShareAttributes(); } } @@ -105,6 +107,7 @@ public void endElement(String uri, String localName, String qName) throws SAXExc CloudFileShare retShare = this.serviceClient.getShareReference(this.shareName); retShare.setMetadata(this.attributes.getMetadata()); retShare.setProperties(this.attributes.getProperties()); + retShare.snapshotID = this.snapshotID; this.response.getResults().add(retShare); } @@ -134,6 +137,9 @@ else if (FileConstants.SHARE_ELEMENT.equals(parentNode)) { if (Constants.NAME_ELEMENT.equals(currentNode)) { this.shareName = value; } + else if (Constants.QueryConstants.SNAPSHOT.equals(currentNode.toLowerCase())) { + this.snapshotID = value; + } } else if (Constants.PROPERTIES.equals(parentNode)) { try { diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListingDetails.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListingDetails.java index b9b54ddb0..87640da89 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListingDetails.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListingDetails.java @@ -18,6 +18,12 @@ * Specifies which details to include when listing the shares in this storage account. */ public enum ShareListingDetails { + + /** + * Specifies including no additional details. + */ + NONE(0), + /** * Specifies including all available details. */ @@ -26,12 +32,12 @@ public enum ShareListingDetails { /** * Specifies including share metadata. */ - METADATA(1), + METADATA(1); /** - * Specifies including no additional details. + * Specifies listing share snapshots. */ - NONE(0); + //SNAPSHOTS(2); /** * Returns the value of this enum. From 5588a6040fb413d7871a986a66cb0ef56cef651b Mon Sep 17 00:00:00 2001 From: Josh Friedman Date: Mon, 15 May 2017 12:21:35 -0700 Subject: [PATCH 2/8] 5.2.0 Release --- ChangeLog.txt | 9 + README.md | 2 +- microsoft-azure-storage-samples/pom.xml | 2 +- .../microsoft/azure/storage/Constants.java | 4 +- .../azure/storage/core/ExecutionEngine.java | 4 +- .../azure/storage/file/CloudFile.java | 157 +++++++----------- .../storage/file/CloudFileDirectory.java | 71 ++++---- .../azure/storage/file/CloudFileShare.java | 8 +- .../azure/storage/file/FileRequest.java | 69 ++++---- pom.xml | 2 +- 10 files changed, 135 insertions(+), 193 deletions(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index ec21f9dd6..f7b66cd7c 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,3 +1,12 @@ +2017.05.15 Version 5.2.0 + * Fixed Exists() calls on Shares and Directories to now populate metadata. This was already being done for Files. + * Changed blob constants to support up to 256 MB on put blob for block blobs. The default value for put blob threshold has also been updated to half of the maximum, or 128 MB currently. + * Fixed a bug that prevented setting content MD5 to true when creating a new file. + * Fixed a bug where access conditions, options, and operation context were not being passed when calling openWriteExisting() on a page blob or a file. + * Fixed a bug where an exception was being thrown on a range get of a blob or file when the options disableContentMD5Validation is set to false and useTransactionalContentMD5 is set to true and there is no overall MD5. + * Fixed a bug where retries were happening immediately if a socket exception was thrown. + * In CloudFileShareProperties, setShareQuota() no longer asserts in bounds. This check has been moved to create() and uploadProperties() in CloudFileShare. + 2017.05.14 Version 5.1.1 * Reverted version 5.1.0 due to a regression which was caught after publishing. Version 5.2.0 will be released that contains the fixes from 5.1.0 without the regression. diff --git a/README.md b/README.md index 0dc13920e..400d0b864 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ To get the binaries of this library as distributed by Microsoft, ready for use w com.microsoft.azure azure-storage - 5.1.1 + 5.2.0 ``` diff --git a/microsoft-azure-storage-samples/pom.xml b/microsoft-azure-storage-samples/pom.xml index 0783b583e..54e1575ea 100644 --- a/microsoft-azure-storage-samples/pom.xml +++ b/microsoft-azure-storage-samples/pom.xml @@ -26,7 +26,7 @@ com.microsoft.azure azure-storage - 5.1.1 + 5.2.0 com.microsoft.azure diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/Constants.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/Constants.java index 556c88456..99d4493a4 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/Constants.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/Constants.java @@ -641,7 +641,7 @@ public static class HeaderConstants { /** * The current storage version header value. */ - public static final String TARGET_STORAGE_VERSION = "2016-10-16"; + public static final String TARGET_STORAGE_VERSION = "2016-05-31"; /** * The header that specifies the next visible time for a queue message. @@ -661,7 +661,7 @@ public static class HeaderConstants { /** * Specifies the value to use for UserAgent header. */ - public static final String USER_AGENT_VERSION = "5.1.1"; + public static final String USER_AGENT_VERSION = "5.2.0"; /** * The default type for content-type and accept diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java index 32f43bcf6..414eabc69 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java @@ -112,13 +112,13 @@ public static RESULT_TYPE executeWithRet // 6. Process the request - Get response RequestResult currResult = task.getResult(); - currResult.setStartDate(new Date()); Logger.info(opContext, LogConstants.GET_RESPONSE); try { currResult.setStatusCode(request.getResponseCode()); currResult.setStatusMessage(request.getResponseMessage()); - } finally { + } + finally { currResult.setStopDate(new Date()); } diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFile.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFile.java index 749e9304c..b9406cbf6 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFile.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFile.java @@ -154,9 +154,8 @@ public CloudFile(final StorageUri fileAbsoluteUri) throws StorageException, URIS * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ - public CloudFile(final URI fileAbsoluteUri, final StorageCredentials credentials) throws StorageException, URISyntaxException { + public CloudFile(final URI fileAbsoluteUri, final StorageCredentials credentials) throws StorageException { this(new StorageUri(fileAbsoluteUri), credentials); } @@ -171,9 +170,8 @@ public CloudFile(final URI fileAbsoluteUri, final StorageCredentials credentials * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ - public CloudFile(final StorageUri fileAbsoluteUri, final StorageCredentials credentials) throws StorageException, URISyntaxException { + public CloudFile(final StorageUri fileAbsoluteUri, final StorageCredentials credentials) throws StorageException { this.parseQueryAndVerify(fileAbsoluteUri, credentials); } @@ -231,10 +229,9 @@ protected CloudFile(final StorageUri uri, final String fileName, final CloudFile * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public final void abortCopy(final String copyId) throws StorageException, URISyntaxException { + public final void abortCopy(final String copyId) throws StorageException { this.abortCopy(copyId, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -255,17 +252,16 @@ public final void abortCopy(final String copyId) throws StorageException, URISyn * the operation. * * @throws StorageException - * If a storage service error occurred. - * @throws URISyntaxException + * If a storage service error occurred. */ @DoesServiceRequest public final void abortCopy(final String copyId, final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, URISyntaxException { + OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -432,10 +428,9 @@ public final String startCopy(final CloudFile sourceFile, final AccessCondition * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public final String startCopy(final URI source) throws StorageException, URISyntaxException { + public final String startCopy(final URI source) throws StorageException { return this.startCopy(source, null /* sourceAccessCondition */, null /* destinationAccessCondition */, null /* options */, null /* opContext */); } @@ -463,18 +458,17 @@ public final String startCopy(final URI source) throws StorageException, URISynt * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException * */ @DoesServiceRequest public final String startCopy(final URI source, final AccessCondition sourceAccessCondition, final AccessCondition destinationAccessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException, URISyntaxException { + throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -544,10 +538,9 @@ public String preProcessResponse(CloudFile file, CloudFileClient client, Operati * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public void clearRange(final long offset, final long length) throws StorageException, URISyntaxException { + public void clearRange(final long offset, final long length) throws StorageException { this.clearRange(offset, length, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -574,16 +567,15 @@ public void clearRange(final long offset, final long length) throws StorageExcep * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public void clearRange(final long offset, final long length, final AccessCondition accessCondition, - FileRequestOptions options, OperationContext opContext) throws StorageException, URISyntaxException { + FileRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -600,11 +592,10 @@ public void clearRange(final long offset, final long length, final AccessConditi * A long which represents the size, in bytes, of the file. * * @throws StorageException - * If a storage service error occurred. - * @throws URISyntaxException + * If a storage service error occurred. */ @DoesServiceRequest - public void create(final long size) throws StorageException, URISyntaxException { + public void create(final long size) throws StorageException { this.create(size, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -627,17 +618,16 @@ public void create(final long size) throws StorageException, URISyntaxException * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public void create(final long size, final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, URISyntaxException { + OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -690,10 +680,9 @@ public Void preProcessResponse(CloudFile file, CloudFileClient client, Operation * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public final void delete() throws StorageException, URISyntaxException { + public final void delete() throws StorageException { this.delete(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -713,16 +702,15 @@ public final void delete() throws StorageException, URISyntaxException { * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public final void delete(final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, URISyntaxException { + OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -738,11 +726,9 @@ public final void delete(final AccessCondition accessCondition, FileRequestOptio * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException - * */ @DoesServiceRequest - public final boolean deleteIfExists() throws StorageException, URISyntaxException { + public final boolean deleteIfExists() throws StorageException { return this.deleteIfExists(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -764,13 +750,12 @@ public final boolean deleteIfExists() throws StorageException, URISyntaxExceptio * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public final boolean deleteIfExists(final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, URISyntaxException { + OperationContext opContext) throws StorageException { options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); boolean exists = this.exists(true, accessCondition, options, opContext); if (exists) { @@ -1289,7 +1274,7 @@ public void setRequestLocationMode() { public HttpURLConnection buildRequest(CloudFileClient client, CloudFile file, OperationContext context) throws Exception { return FileRequest.getFileRanges(file.getTransformedAddress(context).getUri(this.getCurrentLocation()), - options, context, accessCondition, file.getShare().snapshotID); + options, context, accessCondition); } @Override @@ -1356,7 +1341,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFile file, Op // : accessCondition; return FileRequest.getFile(file.getTransformedAddress(context).getUri(this.getCurrentLocation()), - options, context, accessCondition, file.getShare().snapshotID, this.getOffset(), this.getLength(), + options, context, accessCondition, this.getOffset(), this.getLength(), (options.getUseTransactionalContentMD5() && !this.getArePropertiesPopulated())); } @@ -1531,7 +1516,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFile file, Op throws Exception { return FileRequest.getFileProperties( file.getTransformedAddress(context).getUri(this.getCurrentLocation()), - options, context, accessCondition, file.getShare().snapshotID); + options, context, accessCondition); } @Override @@ -1628,7 +1613,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFile file, Op throws Exception { return FileRequest.getFileProperties( file.getTransformedAddress(context).getUri(this.getCurrentLocation()), - options, context, accessCondition, file.getShare().snapshotID); + options, context, accessCondition); } @Override @@ -1850,10 +1835,9 @@ public final FileInputStream openRead(final AccessCondition accessCondition, Fil * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public FileOutputStream openWriteExisting() throws StorageException, URISyntaxException { + public FileOutputStream openWriteExisting() throws StorageException { return this .openOutputStreamInternal(null /* length */, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -1877,11 +1861,10 @@ public FileOutputStream openWriteExisting() throws StorageException, URISyntaxEx * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public FileOutputStream openWriteExisting(AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, URISyntaxException { + OperationContext opContext) throws StorageException { return this.openOutputStreamInternal(null /* length */, accessCondition, options, opContext); } @@ -1900,10 +1883,9 @@ public FileOutputStream openWriteExisting(AccessCondition accessCondition, FileR * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public FileOutputStream openWriteNew(final long length) throws StorageException, URISyntaxException { + public FileOutputStream openWriteNew(final long length) throws StorageException { return this .openOutputStreamInternal(length, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -1933,11 +1915,10 @@ public FileOutputStream openWriteNew(final long length) throws StorageException, * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public FileOutputStream openWriteNew(final long length, AccessCondition accessCondition, - FileRequestOptions options, OperationContext opContext) throws StorageException, URISyntaxException { + FileRequestOptions options, OperationContext opContext) throws StorageException { return openOutputStreamInternal(length, accessCondition, options, opContext); } @@ -1964,15 +1945,14 @@ public FileOutputStream openWriteNew(final long length, AccessCondition accessCo * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ private FileOutputStream openOutputStreamInternal(Long length, AccessCondition accessCondition, - FileRequestOptions options, OperationContext opContext) throws StorageException, URISyntaxException { + FileRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient, false /* setStartTime */); @@ -2008,10 +1988,9 @@ private FileOutputStream openOutputStreamInternal(Long length, AccessCondition a * @throws StorageException * If a storage service error occurred. * @throws IOException - * @throws URISyntaxException */ public void uploadFromByteArray(final byte[] buffer, final int offset, final int length) throws StorageException, - IOException, URISyntaxException { + IOException { uploadFromByteArray(buffer, offset, length, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2038,11 +2017,10 @@ public void uploadFromByteArray(final byte[] buffer, final int offset, final int * @throws StorageException * If a storage service error occurred. * @throws IOException - * @throws URISyntaxException */ public void uploadFromByteArray(final byte[] buffer, final int offset, final int length, final AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException, IOException, URISyntaxException { + throws StorageException, IOException { ByteArrayInputStream inputStream = new ByteArrayInputStream(buffer, offset, length); this.upload(inputStream, length, accessCondition, options, opContext); inputStream.close(); @@ -2057,9 +2035,8 @@ public void uploadFromByteArray(final byte[] buffer, final int offset, final int * @throws StorageException * If a storage service error occurred. * @throws IOException - * @throws URISyntaxException */ - public void uploadFromFile(final String path) throws StorageException, IOException, URISyntaxException { + public void uploadFromFile(final String path) throws StorageException, IOException { uploadFromFile(path, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2082,10 +2059,9 @@ public void uploadFromFile(final String path) throws StorageException, IOExcepti * @throws StorageException * If a storage service error occurred. * @throws IOException - * @throws URISyntaxException */ public void uploadFromFile(final String path, final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, IOException, URISyntaxException { + OperationContext opContext) throws StorageException, IOException { File file = new File(path); long fileLength = file.length(); InputStream inputStream = new BufferedInputStream(new java.io.FileInputStream(file)); @@ -2103,9 +2079,8 @@ public void uploadFromFile(final String path, final AccessCondition accessCondit * @throws StorageException * If a storage service error occurred. * @throws IOException - * @throws URISyntaxException */ - public void uploadText(final String content) throws StorageException, IOException, URISyntaxException { + public void uploadText(final String content) throws StorageException, IOException { this.uploadText(content, null /* charsetName */, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2132,10 +2107,9 @@ public void uploadText(final String content) throws StorageException, IOExceptio * @throws StorageException * If a storage service error occurred. * @throws IOException - * @throws URISyntaxException */ public void uploadText(final String content, final String charsetName, final AccessCondition accessCondition, - FileRequestOptions options, OperationContext opContext) throws StorageException, IOException, URISyntaxException { + FileRequestOptions options, OperationContext opContext) throws StorageException, IOException { byte[] bytes = (charsetName == null) ? content.getBytes() : content.getBytes(charsetName); this.uploadFromByteArray(bytes, 0, bytes.length, accessCondition, options, opContext); } @@ -2155,11 +2129,10 @@ public void uploadText(final String content, final String charsetName, final Acc * If an I/O exception occurred. * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public void uploadRange(final InputStream sourceStream, final long offset, final long length) - throws StorageException, IOException, URISyntaxException { + throws StorageException, IOException { this.uploadRange(sourceStream, offset, length, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2188,17 +2161,16 @@ public void uploadRange(final InputStream sourceStream, final long offset, final * If an I/O exception occurred. * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public void uploadRange(final InputStream sourceStream, final long offset, final long length, final AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException, IOException, URISyntaxException { + throws StorageException, IOException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -2327,10 +2299,9 @@ public Void preProcessResponse(CloudFile file, CloudFileClient client, Operation * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public final void uploadMetadata() throws StorageException, URISyntaxException { + public final void uploadMetadata() throws StorageException { this.uploadMetadata(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2354,17 +2325,16 @@ public final void uploadMetadata() throws StorageException, URISyntaxException { * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public final void uploadMetadata(final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, URISyntaxException { + OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -2421,10 +2391,9 @@ public Void preProcessResponse(CloudFile file, CloudFileClient client, Operation * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public final void uploadProperties() throws StorageException, URISyntaxException { + public final void uploadProperties() throws StorageException { this.uploadProperties(null /* accessCondition */, null /* options */, null /*opContext */); } @@ -2447,16 +2416,15 @@ public final void uploadProperties() throws StorageException, URISyntaxException * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public final void uploadProperties(final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, URISyntaxException { + OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -2509,9 +2477,8 @@ public Void preProcessResponse(CloudFile file, CloudFileClient client, Operation * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ - public void resize(long size) throws StorageException, URISyntaxException { + public void resize(long size) throws StorageException { this.resize(size, null /* accessCondition */, null /* options */, null /* operationContext */); } @@ -2533,15 +2500,14 @@ public void resize(long size) throws StorageException, URISyntaxException { * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ public void resize(long size, AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, URISyntaxException { + OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -2597,10 +2563,9 @@ public Void preProcessResponse(CloudFile file, CloudFileClient client, Operation * If an I/O exception occurred. * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public void upload(final InputStream sourceStream, final long length) throws StorageException, IOException, URISyntaxException { + public void upload(final InputStream sourceStream, final long length) throws StorageException, IOException { this.upload(sourceStream, length, null /* accessCondition */, null /* options */, null /* opContext */); } @@ -2627,17 +2592,16 @@ public void upload(final InputStream sourceStream, final long length) throws Sto * @throws IOException * If an I/O exception occurred. * @throws StorageException - * If a storage service error occurred. - * @throws URISyntaxException + * If a storage service error occurred. */ @DoesServiceRequest public void upload(final InputStream sourceStream, final long length, final AccessCondition accessCondition, - FileRequestOptions options, OperationContext opContext) throws StorageException, IOException, URISyntaxException { + FileRequestOptions options, OperationContext opContext) throws StorageException, IOException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -2727,10 +2691,9 @@ protected static String getParentNameFromURI(final StorageUri resourceAddress, f * A {@link StorageCredentials} object used to authenticate access. * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCredentials credentials) - throws StorageException, URISyntaxException { + throws StorageException { Utility.assertNotNull("completeUri", completeUri); if (!completeUri.isAbsolute()) { @@ -2756,12 +2719,12 @@ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCred throw Utility.generateNewUnexpectedStorageException(e); } - final HashMap queryParameters = PathUtility.parseQueryString(completeUri.getQuery()); +// final HashMap queryParameters = PathUtility.parseQueryString(completeUri.getQuery()); - final String[] snapshotIDs = queryParameters.get(Constants.QueryConstants.SHARE_SNAPSHOT); - if (snapshotIDs != null && snapshotIDs.length > 0) { - this.getShare().snapshotID = snapshotIDs[0]; - } +// final String[] snapshotIDs = queryParameters.get(Constants.QueryConstants.SHARE_SNAPSHOT); +// if (snapshotIDs != null && snapshotIDs.length > 0) { +// this.getShare().snapshotID = snapshotIDs[0]; +// } } protected void updateEtagAndLastModifiedFromResponse(HttpURLConnection request) { diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileDirectory.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileDirectory.java index fcb275f32..b2d063e6c 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileDirectory.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileDirectory.java @@ -94,9 +94,8 @@ public final class CloudFileDirectory implements ListFileItem { * @param directoryAbsoluteUri * A {@link URI} that represents the file directory's address. * @throws StorageException - * @throws URISyntaxException */ - public CloudFileDirectory(final URI directoryAbsoluteUri) throws StorageException, URISyntaxException { + public CloudFileDirectory(final URI directoryAbsoluteUri) throws StorageException { this(new StorageUri(directoryAbsoluteUri)); } @@ -106,9 +105,8 @@ public CloudFileDirectory(final URI directoryAbsoluteUri) throws StorageExceptio * @param directoryAbsoluteUri * A {@link StorageUri} that represents the file directory's address. * @throws StorageException - * @throws URISyntaxException */ - public CloudFileDirectory(final StorageUri directoryAbsoluteUri) throws StorageException, URISyntaxException { + public CloudFileDirectory(final StorageUri directoryAbsoluteUri) throws StorageException { this(directoryAbsoluteUri, (StorageCredentials) null); } @@ -121,10 +119,9 @@ public CloudFileDirectory(final StorageUri directoryAbsoluteUri) throws StorageE * @param credentials * A {@link StorageCredentials} object used to authenticate access. * @throws StorageException - * @throws URISyntaxException */ public CloudFileDirectory(final URI directoryAbsoluteUri, final StorageCredentials credentials) - throws StorageException, URISyntaxException { + throws StorageException { this(new StorageUri(directoryAbsoluteUri), credentials); } @@ -137,10 +134,9 @@ public CloudFileDirectory(final URI directoryAbsoluteUri, final StorageCredentia * @param credentials * A {@link StorageCredentials} object used to authenticate access. * @throws StorageException - * @throws URISyntaxException */ public CloudFileDirectory(final StorageUri directoryAbsoluteUri, final StorageCredentials credentials) - throws StorageException, URISyntaxException { + throws StorageException { this.parseQueryAndVerify(directoryAbsoluteUri, credentials); } @@ -171,10 +167,9 @@ protected CloudFileDirectory(final StorageUri uri, final String directoryName, f * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public void create() throws StorageException, URISyntaxException { + public void create() throws StorageException { this.create(null /* options */, null /* opContext */); } @@ -192,15 +187,14 @@ public void create() throws StorageException, URISyntaxException { * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public void create(FileRequestOptions options, OperationContext opContext) throws StorageException, URISyntaxException { + public void create(FileRequestOptions options, OperationContext opContext) throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -258,10 +252,9 @@ public Void preProcessResponse(CloudFileDirectory directory, CloudFileClient cli * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public boolean createIfNotExists() throws StorageException, URISyntaxException { + public boolean createIfNotExists() throws StorageException { return this.createIfNotExists(null /* options */, null /* opContext */); } @@ -281,13 +274,12 @@ public boolean createIfNotExists() throws StorageException, URISyntaxException { * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public boolean createIfNotExists(FileRequestOptions options, OperationContext opContext) throws StorageException, URISyntaxException { + public boolean createIfNotExists(FileRequestOptions options, OperationContext opContext) throws StorageException { options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); boolean exists = this.exists(true /* primaryOnly */, null /* accessCondition */, options, opContext); if (exists) { @@ -315,10 +307,9 @@ public boolean createIfNotExists(FileRequestOptions options, OperationContext op * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public void delete() throws StorageException, URISyntaxException { + public void delete() throws StorageException { this.delete(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -338,16 +329,15 @@ public void delete() throws StorageException, URISyntaxException { * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public void delete(AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException, URISyntaxException { + throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -394,10 +384,9 @@ public Void preProcessResponse(CloudFileDirectory directory, CloudFileClient cli * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public boolean deleteIfExists() throws StorageException, URISyntaxException { + public boolean deleteIfExists() throws StorageException { return this.deleteIfExists(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -419,11 +408,10 @@ public boolean deleteIfExists() throws StorageException, URISyntaxException { * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public boolean deleteIfExists(AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException, URISyntaxException { + OperationContext opContext) throws StorageException { options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); boolean exists = this.exists(true /* primaryOnly */, accessCondition, options, opContext); @@ -516,7 +504,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFileDirectory OperationContext context) throws Exception { return FileRequest.getDirectoryProperties( directory.getTransformedAddress().getUri(this.getCurrentLocation()), options, context, - accessCondition, directory.getShare().snapshotID); + accessCondition); } @Override @@ -570,10 +558,9 @@ private void updatePropertiesFromResponse(HttpURLConnection request) { * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest - public void uploadMetadata() throws StorageException, URISyntaxException { + public void uploadMetadata() throws StorageException { this.uploadMetadata(null /* accessCondition */, null /* options */, null /* opContext */); } @@ -593,16 +580,15 @@ public void uploadMetadata() throws StorageException, URISyntaxException { * * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ @DoesServiceRequest public void uploadMetadata(AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException, URISyntaxException { + throws StorageException { if (opContext == null) { opContext = new OperationContext(); } - this.getShare().assertNoSnapshot(); + //this.getShare().assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -707,7 +693,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFileDirectory OperationContext context) throws Exception { return FileRequest.getDirectoryProperties( directory.getTransformedAddress().getUri(this.getCurrentLocation()), options, context, - accessCondition, directory.getShare().snapshotID); + accessCondition); } @Override @@ -928,7 +914,7 @@ public HttpURLConnection buildRequest(CloudFileClient client, CloudFileDirectory .getNextMarker() : null); return FileRequest.listFilesAndDirectories( directory.getTransformedAddress().getUri(this.getCurrentLocation()), - options, context, listingContext, directory.getShare().snapshotID); + options, context, listingContext); } @Override @@ -1164,10 +1150,9 @@ protected void setStorageUri(final StorageUri storageUri) { * A {@link StorageCredentials} object used to authenticate access. * @throws StorageException * If a storage service error occurred. - * @throws URISyntaxException */ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCredentials credentials) - throws StorageException, URISyntaxException { + throws StorageException { Utility.assertNotNull("completeUri", completeUri); if (!completeUri.isAbsolute()) { @@ -1193,12 +1178,12 @@ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCred throw Utility.generateNewUnexpectedStorageException(e); } - final HashMap queryParameters = PathUtility.parseQueryString(completeUri.getQuery()); - - final String[] snapshotIDs = queryParameters.get(Constants.QueryConstants.SHARE_SNAPSHOT); - if (snapshotIDs != null && snapshotIDs.length > 0) { - this.getShare().snapshotID = snapshotIDs[0]; - } +// final HashMap queryParameters = PathUtility.parseQueryString(completeUri.getQuery()); +// +// final String[] snapshotIDs = queryParameters.get(Constants.QueryConstants.SHARE_SNAPSHOT); +// if (snapshotIDs != null && snapshotIDs.length > 0) { +// this.getShare().snapshotID = snapshotIDs[0]; +// } } /** diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java index d3d180261..f5a3eaf92 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java @@ -155,8 +155,6 @@ public CloudFileShare(final StorageUri storageUri) throws StorageException { * A java.net.URI object that represents the absolute URI of the share. * @param credentials * A {@link StorageCredentials} object used to authenticate access. - * @param snapshotID - * A String that represents the snapshot version, if applicable. * * @throws StorageException * If a storage service error occurred. @@ -418,7 +416,7 @@ private StorageRequest deleteImpl( public HttpURLConnection buildRequest( CloudFileClient client, CloudFileShare share, OperationContext context) throws Exception { return FileRequest.deleteShare( - share.getTransformedAddress().getPrimaryUri(), options, context, accessCondition, share.snapshotID, deleteSnapshotsOption); + share.getTransformedAddress().getPrimaryUri(), options, context, accessCondition); } @Override @@ -590,7 +588,7 @@ public void setRequestLocationMode() { public HttpURLConnection buildRequest(CloudFileClient client, CloudFileShare share, OperationContext context) throws Exception { return FileRequest.getShareProperties(share.getTransformedAddress().getUri(this.getCurrentLocation()), - options, context, accessCondition, share.snapshotID); + options, context, accessCondition); } @Override @@ -1006,7 +1004,7 @@ public void setRequestLocationMode() { public HttpURLConnection buildRequest(CloudFileClient client, CloudFileShare share, OperationContext context) throws Exception { return FileRequest.getShareProperties(share.getTransformedAddress().getUri(this.getCurrentLocation()), - options, context, accessCondition, share.snapshotID); + options, context, accessCondition); } @Override diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileRequest.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileRequest.java index 092f4866a..fc29553cf 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileRequest.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/FileRequest.java @@ -131,7 +131,7 @@ private static void addProperties(final HttpURLConnection request, FilePropertie * the share snapshot version to the query builder. * @throws StorageException */ - public static void addShareSnapshot(final UriQueryBuilder builder, final String snapshotVersion) + protected static void addShareSnapshot(final UriQueryBuilder builder, final String snapshotVersion) throws StorageException { if (snapshotVersion != null) { builder.add(Constants.QueryConstants.SHARE_SNAPSHOT, snapshotVersion); @@ -288,26 +288,26 @@ public static HttpURLConnection deleteFile(final URI uri, final FileRequestOptio * @throws IllegalArgumentException */ public static HttpURLConnection deleteShare(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, final AccessCondition accessCondition, String snapshotVersion, DeleteShareSnapshotsOption deleteSnapshotsOption) + final OperationContext opContext, final AccessCondition accessCondition) throws IOException, URISyntaxException, StorageException { final UriQueryBuilder shareBuilder = getShareUriQueryBuilder(); - FileRequest.addShareSnapshot(shareBuilder, snapshotVersion); + //FileRequest.addShareSnapshot(shareBuilder, snapshotVersion); HttpURLConnection request = BaseRequest.delete(uri, fileOptions, shareBuilder, opContext); if (accessCondition != null) { accessCondition.applyConditionToRequest(request); } - switch (deleteSnapshotsOption) { - case NONE: - // nop - break; - case INCLUDE_SNAPSHOTS: - request.setRequestProperty(Constants.HeaderConstants.DELETE_SNAPSHOT_HEADER, - Constants.HeaderConstants.INCLUDE_SNAPSHOTS_VALUE); - break; - default: - break; - } +// switch (deleteSnapshotsOption) { +// case NONE: +// // nop +// break; +// case INCLUDE_SNAPSHOTS: +// request.setRequestProperty(Constants.HeaderConstants.DELETE_SNAPSHOT_HEADER, +// Constants.HeaderConstants.INCLUDE_SNAPSHOTS_VALUE); +// break; +// default: +// break; +// } return request; } @@ -362,8 +362,6 @@ public static HttpURLConnection getAcl(final URI uri, final FileRequestOptions f * the operation. * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the file. - * @param snapshotVersion - * The snapshot version, if the share is a snapshot. * @param offset * The offset at which to begin returning content. * @param count @@ -380,7 +378,7 @@ public static HttpURLConnection getAcl(final URI uri, final FileRequestOptions f * @throws IllegalArgumentException */ public static HttpURLConnection getFile(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, final AccessCondition accessCondition, final String snapshotVersion, final Long offset, + final OperationContext opContext, final AccessCondition accessCondition, final Long offset, final Long count, boolean requestRangeContentMD5) throws IOException, URISyntaxException, StorageException { if (offset != null && requestRangeContentMD5) { @@ -389,7 +387,7 @@ public static HttpURLConnection getFile(final URI uri, final FileRequestOptions } final UriQueryBuilder builder = new UriQueryBuilder(); - FileRequest.addShareSnapshot(builder, snapshotVersion); + //FileRequest.addShareSnapshot(builder, snapshotVersion); final HttpURLConnection request = BaseRequest.createURLConnection(uri, fileOptions, builder, opContext); request.setRequestMethod(Constants.HTTP_GET); @@ -434,8 +432,6 @@ public static HttpURLConnection getFile(final URI uri, final FileRequestOptions * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the file. * @return a HttpURLConnection to use to perform the operation. - * @param snapshotVersion - * the snapshot version to the query builder. * @throws IOException * if there is an error opening the connection * @throws URISyntaxException @@ -445,11 +441,11 @@ public static HttpURLConnection getFile(final URI uri, final FileRequestOptions * @throws IllegalArgumentException */ public static HttpURLConnection getFileProperties(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, final AccessCondition accessCondition, final String snapshotVersion) throws StorageException, + final OperationContext opContext, final AccessCondition accessCondition) throws StorageException, IOException, URISyntaxException { final UriQueryBuilder builder = new UriQueryBuilder(); - return getProperties(uri, fileOptions, opContext, accessCondition, builder, snapshotVersion); + return getProperties(uri, fileOptions, opContext, accessCondition, builder); } /** @@ -479,11 +475,11 @@ public static HttpURLConnection getFileProperties(final URI uri, final FileReque * @throws IllegalArgumentException */ public static HttpURLConnection getFileRanges(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, final AccessCondition accessCondition, final String snapshotVersion) throws StorageException, + final OperationContext opContext, final AccessCondition accessCondition) throws StorageException, IOException, URISyntaxException { final UriQueryBuilder builder = new UriQueryBuilder(); - addShareSnapshot(builder, snapshotVersion); + //addShareSnapshot(builder, snapshotVersion); builder.add(Constants.QueryConstants.COMPONENT, RANGE_LIST_QUERY_ELEMENT_NAME); final HttpURLConnection request = BaseRequest.createURLConnection(uri, fileOptions, builder, opContext); @@ -511,17 +507,15 @@ public static HttpURLConnection getFileRanges(final URI uri, final FileRequestOp * the operation. * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the share. - * @param snapshotVersion - * the snapshot version to the query builder. * @return a HttpURLConnection configured for the operation. * @throws StorageException * */ public static HttpURLConnection getShareProperties(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, AccessCondition accessCondition, final String snapshotVersion) throws IOException, URISyntaxException, + final OperationContext opContext, AccessCondition accessCondition) throws IOException, URISyntaxException, StorageException { final UriQueryBuilder shareBuilder = getShareUriQueryBuilder(); - return getProperties(uri, fileOptions, opContext, accessCondition, shareBuilder, snapshotVersion); + return getProperties(uri, fileOptions, opContext, accessCondition, shareBuilder); } /** @@ -604,16 +598,13 @@ private static UriQueryBuilder getDirectoryUriQueryBuilder() throws StorageExcep * the operation. * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the share. - * @param snapshotVersion - * the snapshot version to the query builder. * @return a HttpURLConnection configured for the operation. * @throws StorageException * */ private static HttpURLConnection getProperties(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, AccessCondition accessCondition, final UriQueryBuilder builder, - String snapshotVersion) + final OperationContext opContext, AccessCondition accessCondition, final UriQueryBuilder builder) throws IOException, URISyntaxException, StorageException { - addShareSnapshot(builder, snapshotVersion); + //addShareSnapshot(builder, snapshotVersion); HttpURLConnection request = BaseRequest.getProperties(uri, fileOptions, builder, opContext); if (accessCondition != null) { @@ -810,16 +801,14 @@ public static HttpURLConnection deleteDirectory(final URI uri, final FileRequest * the operation. * @param accessCondition * An {@link AccessCondition} object that represents the access conditions for the directory. - * @param snapshotVersion - * the snapshot version to the query builder. * @return a HttpURLConnection configured for the operation. * @throws StorageException * */ public static HttpURLConnection getDirectoryProperties(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, AccessCondition accessCondition, String snapshotVersion) throws IOException, URISyntaxException, + final OperationContext opContext, AccessCondition accessCondition) throws IOException, URISyntaxException, StorageException { final UriQueryBuilder directoryBuilder = getDirectoryUriQueryBuilder(); - return getProperties(uri, fileOptions, opContext, accessCondition, directoryBuilder, snapshotVersion); + return getProperties(uri, fileOptions, opContext, accessCondition, directoryBuilder); } /** @@ -838,8 +827,6 @@ public static HttpURLConnection getDirectoryProperties(final URI uri, final File * the operation. * @param listingContext * A set of parameters for the listing operation. - * @param snapshotVersion - * the snapshot version to the query builder. * @return a HttpURLConnection configured for the operation. * @throws IOException * @throws URISyntaxException @@ -847,11 +834,11 @@ public static HttpURLConnection getDirectoryProperties(final URI uri, final File * @throws IllegalArgumentException */ public static HttpURLConnection listFilesAndDirectories(final URI uri, final FileRequestOptions fileOptions, - final OperationContext opContext, final ListingContext listingContext, String snapshotVersion) throws URISyntaxException, + final OperationContext opContext, final ListingContext listingContext) throws URISyntaxException, IOException, StorageException { final UriQueryBuilder builder = getDirectoryUriQueryBuilder(); - addShareSnapshot(builder, snapshotVersion); + //addShareSnapshot(builder, snapshotVersion); builder.add(Constants.QueryConstants.COMPONENT, Constants.QueryConstants.LIST); if (listingContext != null) { diff --git a/pom.xml b/pom.xml index fe30e530d..1798b7d4b 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ 4.0.0 com.microsoft.azure azure-storage - 5.1.1 + 5.2.0 jar Microsoft Azure Storage Client SDK From 0348c8f15167c0c17eb965ef7a0fd2769310a6c9 Mon Sep 17 00:00:00 2001 From: Josh Friedman Date: Mon, 15 May 2017 12:44:48 -0700 Subject: [PATCH 3/8] Updating tests for 5.2.0 Release --- .../azure/storage/file/CloudFileDirectoryTests.java | 2 -- .../com/microsoft/azure/storage/file/CloudFileTests.java | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java index f9e87412c..ec4afc27f 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java @@ -874,8 +874,6 @@ public void eventOccurred(SendingRequestEvent eventArg) { } catch (StorageException e) { fail("Delete should succeed."); - } catch (URISyntaxException e) { - fail("Delete should succeed."); } } } diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java index 9bf77cfb9..3011d6844 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java @@ -1414,8 +1414,6 @@ public void eventOccurred(SendingRequestEvent eventArg) { } catch (StorageException e) { fail("Delete should succeed."); - } catch (URISyntaxException e) { - fail("Delete should succeed."); } } } @@ -1464,8 +1462,8 @@ public void testFileGetRangeContentMD5Bounds() throws StorageException, IOExcept FileRequestOptions options = new FileRequestOptions(); OperationContext opContext = new OperationContext(); try { - FileRequest.getFile(file.getUri(), options, opContext, null, null, 0L, 4L * Constants.MB, true); - FileRequest.getFile(file.getUri(), options, opContext, null, null, 0L, 4L * Constants.MB + 1, true); + FileRequest.getFile(file.getUri(), options, opContext, null, 0L, 4L * Constants.MB, true); + FileRequest.getFile(file.getUri(), options, opContext, null, 0L, 4L * Constants.MB + 1, true); fail("The request for range ContentMD5 should have thrown an Exception for exceeding the limit."); } catch (IllegalArgumentException e) From 8a2bb7381641e0f93fcdecb5a5f22faf973913cf Mon Sep 17 00:00:00 2001 From: Josh Friedman Date: Mon, 15 May 2017 12:54:24 -0700 Subject: [PATCH 4/8] Comment out assertNoSnapshot --- .../azure/storage/file/CloudFileShare.java | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java index f5a3eaf92..28b9904c0 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java @@ -220,7 +220,7 @@ public void create(FileRequestOptions options, OperationContext opContext) throw opContext = new OperationContext(); } - assertNoSnapshot(); + //assertNoSnapshot(); if (this.properties != null && this.properties.getShareQuota() != null) { Utility.assertInBounds("Share Quota", this.properties.getShareQuota(), 1, FileConstants.MAX_SHARE_QUOTA); } @@ -656,7 +656,7 @@ public FileSharePermissions downloadPermissions(AccessCondition accessCondition, opContext = new OperationContext(); } - assertNoSnapshot(); + //assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -781,7 +781,7 @@ protected final CloudFileShare createSnapshot(final AccessCondition accessCondit protected final CloudFileShare createSnapshot(final HashMap metadata, final AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) throws StorageException { - assertNoSnapshot(); + //assertNoSnapshot(); if (opContext == null) { opContext = new OperationContext(); @@ -883,7 +883,7 @@ public ShareStats getStats(FileRequestOptions options, OperationContext opContex opContext = new OperationContext(); } - assertNoSnapshot(); + //assertNoSnapshot(); opContext.initialize(); options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); @@ -1057,14 +1057,14 @@ private void updatePropertiesFromResponse(HttpURLConnection request) { } } - /** - * Asserts that the share is not a snapshot. - */ - protected void assertNoSnapshot() { - if (isSnapshot()) { - throw new IllegalArgumentException(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT); - } - } +// /** +// * Asserts that the share is not a snapshot. +// */ +// protected void assertNoSnapshot() { +// if (isSnapshot()) { +// throw new IllegalArgumentException(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT); +// } +// } /** * Returns a shared access signature for the share. Note this does not contain the leading "?". @@ -1173,7 +1173,7 @@ public void uploadMetadata() throws StorageException { @DoesServiceRequest public void uploadMetadata(AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) throws StorageException { - assertNoSnapshot(); + //assertNoSnapshot(); if (opContext == null) { opContext = new OperationContext(); @@ -1263,7 +1263,7 @@ public final void uploadProperties() throws StorageException { public final void uploadProperties( AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) throws StorageException { - assertNoSnapshot(); + //assertNoSnapshot(); if (this.properties != null && this.properties.getShareQuota() != null) { Utility.assertInBounds("Share Quota", this.properties.getShareQuota(), 1, FileConstants.MAX_SHARE_QUOTA); @@ -1350,7 +1350,7 @@ public void uploadPermissions(final FileSharePermissions permissions) throws Sto @DoesServiceRequest public void uploadPermissions(final FileSharePermissions permissions, final AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) throws StorageException { - assertNoSnapshot(); + //assertNoSnapshot(); if (opContext == null) { opContext = new OperationContext(); From 95dbe094a8e0ea104485934ecb848f78b10a10a6 Mon Sep 17 00:00:00 2001 From: Josh Friedman Date: Wed, 17 May 2017 10:40:37 -0700 Subject: [PATCH 5/8] Revert change to execution engine --- .../src/com/microsoft/azure/storage/file/CloudFileTests.java | 2 +- .../src/com/microsoft/azure/storage/core/ExecutionEngine.java | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java index 3011d6844..f15c20b4a 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java @@ -1,4 +1,4 @@ -/** +/** * Copyright Microsoft Corporation * * Licensed under the Apache License, Version 2.0 (the "License"); diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java index 414eabc69..30b6dad81 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/core/ExecutionEngine.java @@ -112,6 +112,7 @@ public static RESULT_TYPE executeWithRet // 6. Process the request - Get response RequestResult currResult = task.getResult(); + currResult.setStartDate(new Date()); Logger.info(opContext, LogConstants.GET_RESPONSE); try { From 642f17bdb220d199894a768b1cf52992abd383ba Mon Sep 17 00:00:00 2001 From: Josh Friedman Date: Mon, 22 May 2017 16:05:43 -0700 Subject: [PATCH 6/8] Commenting out additional share snapshot changes to be safe --- .../storage/file/CloudFileClientTests.java | 84 ++-- .../storage/file/CloudFileDirectoryTests.java | 128 +++--- .../storage/file/CloudFileShareTests.java | 366 +++++++++--------- .../azure/storage/file/CloudFileTests.java | 198 +++++----- .../azure/storage/file/CloudFileClient.java | 44 +-- .../azure/storage/file/CloudFileShare.java | 344 ++++++++-------- .../azure/storage/file/ShareListHandler.java | 2 +- 7 files changed, 583 insertions(+), 583 deletions(-) diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileClientTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileClientTests.java index f83e4d588..10a0c5986 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileClientTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileClientTests.java @@ -115,46 +115,46 @@ public void testListSharesMaxResultsValidationTest() throws StorageException, UR assertNotNull(fileClient.listSharesSegmented("thereshouldntbeanyshareswiththisprefix")); } - //@Test - public void testListSharesWithSnapshot() throws StorageException, URISyntaxException { - CloudFileClient fileClient = FileTestHelper.createCloudFileClient(); - CloudFileShare share = fileClient.getShareReference(UUID.randomUUID().toString()); - share.create(); - - HashMap shareMeta = new HashMap(); - shareMeta.put("key1", "value1"); - share.setMetadata(shareMeta); - share.uploadMetadata(); - - CloudFileShare snapshot = share.createSnapshot(); - HashMap meta2 = new HashMap(); - meta2.put("key2", "value2"); - share.setMetadata(meta2); - share.uploadMetadata(); - - CloudFileClient client = FileTestHelper.createCloudFileClient(); - Iterable listResult = client.listShares(share.name, ShareListingDetails.ALL, null, null); - - int count = 0; - boolean originalFound = false; - boolean snapshotFound = false; - for (CloudFileShare listShareItem : listResult) { - if (listShareItem.getName().equals(share.getName()) && !listShareItem.isSnapshot() && !originalFound) - { - count++; - originalFound = true; - assertEquals(share.getMetadata(), listShareItem.getMetadata()); - assertEquals(share.getStorageUri(), listShareItem.getStorageUri()); - } - else if (listShareItem.getName().equals(share.getName()) && - listShareItem.isSnapshot() && !snapshotFound) { - count++; - snapshotFound = true; - assertEquals(snapshot.getMetadata(), listShareItem.getMetadata()); - assertEquals(snapshot.getStorageUri(), listShareItem.getStorageUri()); - } - } - - assertEquals(2, count); - } +// @Test +// public void testListSharesWithSnapshot() throws StorageException, URISyntaxException { +// CloudFileClient fileClient = FileTestHelper.createCloudFileClient(); +// CloudFileShare share = fileClient.getShareReference(UUID.randomUUID().toString()); +// share.create(); +// +// HashMap shareMeta = new HashMap(); +// shareMeta.put("key1", "value1"); +// share.setMetadata(shareMeta); +// share.uploadMetadata(); +// +// CloudFileShare snapshot = share.createSnapshot(); +// HashMap meta2 = new HashMap(); +// meta2.put("key2", "value2"); +// share.setMetadata(meta2); +// share.uploadMetadata(); +// +// CloudFileClient client = FileTestHelper.createCloudFileClient(); +// Iterable listResult = client.listShares(share.name, ShareListingDetails.ALL, null, null); +// +// int count = 0; +// boolean originalFound = false; +// boolean snapshotFound = false; +// for (CloudFileShare listShareItem : listResult) { +// if (listShareItem.getName().equals(share.getName()) && !listShareItem.isSnapshot() && !originalFound) +// { +// count++; +// originalFound = true; +// assertEquals(share.getMetadata(), listShareItem.getMetadata()); +// assertEquals(share.getStorageUri(), listShareItem.getStorageUri()); +// } +// else if (listShareItem.getName().equals(share.getName()) && +// listShareItem.isSnapshot() && !snapshotFound) { +// count++; +// snapshotFound = true; +// assertEquals(snapshot.getMetadata(), listShareItem.getMetadata()); +// assertEquals(snapshot.getStorageUri(), listShareItem.getStorageUri()); +// } +// } +// +// assertEquals(2, count); +// } } \ No newline at end of file diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java index ec4afc27f..32f70df70 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileDirectoryTests.java @@ -480,70 +480,70 @@ private static void testMetadataFailures(CloudFileDirectory directory, String ke directory.getMetadata().remove(key); } - //@Test - public void testUnsupportedDirectoryApisWithinShareSnapshot() throws StorageException, URISyntaxException { - CloudFileShare snapshot = this.share.createSnapshot(); - CloudFileDirectory rootDir = snapshot.getRootDirectoryReference(); - try { - rootDir.create(); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - rootDir.delete(); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - rootDir.uploadMetadata(); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - - snapshot.delete(); - } - - //@Test - public void testSupportedDirectoryApisInShareSnapshot() throws StorageException, URISyntaxException { - CloudFileDirectory dir = this.share.getRootDirectoryReference().getDirectoryReference("dir1"); - dir.deleteIfExists(); - dir.create(); - HashMap meta = new HashMap(); - meta.put("key1", "value1"); - dir.setMetadata(meta); - dir.uploadMetadata(); - CloudFileShare snapshot = this.share.createSnapshot(); - CloudFileDirectory snapshotDir = snapshot.getRootDirectoryReference().getDirectoryReference("dir1"); - - HashMap meta2 = new HashMap(); - meta2.put("key2", "value2"); - dir.setMetadata(meta2); - dir.uploadMetadata(); - snapshotDir.downloadAttributes(); - - assertTrue(snapshotDir.getMetadata().size() == 1 && snapshotDir.getMetadata().get("key1").equals("value1")); - assertNotNull(snapshotDir.getProperties().getEtag()); - - dir.downloadAttributes(); - assertTrue(dir.getMetadata().size() == 1 && dir.getMetadata().get("key2").equals("value2")); - assertNotNull(dir.getProperties().getEtag()); - assertNotEquals(dir.getProperties().getEtag(), snapshotDir.getProperties().getEtag()); - - final UriQueryBuilder uriBuilder = new UriQueryBuilder(); - uriBuilder.add("sharesnapshot", snapshot.snapshotID); - uriBuilder.add("restype", "directory"); - CloudFileDirectory snapshotDir2 = new CloudFileDirectory(uriBuilder.addToURI(dir.getUri()), this.share.getServiceClient().getCredentials()); - assertEquals(snapshot.snapshotID, snapshotDir2.getShare().snapshotID); - assertTrue(snapshotDir2.exists()); - - snapshot.delete(); - } +// @Test +// public void testUnsupportedDirectoryApisWithinShareSnapshot() throws StorageException, URISyntaxException { +// CloudFileShare snapshot = this.share.createSnapshot(); +// CloudFileDirectory rootDir = snapshot.getRootDirectoryReference(); +// try { +// rootDir.create(); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// rootDir.delete(); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// rootDir.uploadMetadata(); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// +// snapshot.delete(); +// } + +// @Test +// public void testSupportedDirectoryApisInShareSnapshot() throws StorageException, URISyntaxException { +// CloudFileDirectory dir = this.share.getRootDirectoryReference().getDirectoryReference("dir1"); +// dir.deleteIfExists(); +// dir.create(); +// HashMap meta = new HashMap(); +// meta.put("key1", "value1"); +// dir.setMetadata(meta); +// dir.uploadMetadata(); +// CloudFileShare snapshot = this.share.createSnapshot(); +// CloudFileDirectory snapshotDir = snapshot.getRootDirectoryReference().getDirectoryReference("dir1"); +// +// HashMap meta2 = new HashMap(); +// meta2.put("key2", "value2"); +// dir.setMetadata(meta2); +// dir.uploadMetadata(); +// snapshotDir.downloadAttributes(); +// +// assertTrue(snapshotDir.getMetadata().size() == 1 && snapshotDir.getMetadata().get("key1").equals("value1")); +// assertNotNull(snapshotDir.getProperties().getEtag()); +// +// dir.downloadAttributes(); +// assertTrue(dir.getMetadata().size() == 1 && dir.getMetadata().get("key2").equals("value2")); +// assertNotNull(dir.getProperties().getEtag()); +// assertNotEquals(dir.getProperties().getEtag(), snapshotDir.getProperties().getEtag()); +// +// final UriQueryBuilder uriBuilder = new UriQueryBuilder(); +// uriBuilder.add("sharesnapshot", snapshot.snapshotID); +// uriBuilder.add("restype", "directory"); +// CloudFileDirectory snapshotDir2 = new CloudFileDirectory(uriBuilder.addToURI(dir.getUri()), this.share.getServiceClient().getCredentials()); +// assertEquals(snapshot.snapshotID, snapshotDir2.getShare().snapshotID); +// assertTrue(snapshotDir2.exists()); +// +// snapshot.delete(); +// } /* [TestMethod] diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileShareTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileShareTests.java index 46a84aac4..544adeb11 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileShareTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileShareTests.java @@ -494,195 +494,195 @@ public void eventOccurred(SendingRequestEvent eventArg) { assertTrue(this.share.deleteIfExists(null, null, ctx)); } - //@Test - public void testCreateShareSnapshot() throws StorageException, URISyntaxException, IOException { - // create share with metadata - this.share.create(); - assertTrue(this.share.exists()); - HashMap shareMeta = new HashMap(); - shareMeta.put("key1", "value1"); - this.share.setMetadata(shareMeta); - this.share.uploadMetadata(); - - CloudFileDirectory dir1 = this.share.getRootDirectoryReference().getDirectoryReference("dir1"); - dir1.create(); - CloudFile file1 = dir1.getFileReference("file1"); - file1.create(1024); - ByteArrayInputStream srcStream = FileTestHelper.getRandomDataStream(1024); - file1.upload(srcStream, 1024); - - // create directory with metadata - HashMap dirMeta = new HashMap(); - dirMeta.put("key2", "value2"); - dir1.setMetadata(dirMeta); - dir1.uploadMetadata(); - - // verify that exists() call on snapshot populates metadata - CloudFileShare snapshot = this.share.createSnapshot(); - CloudFileClient client = FileTestHelper.createCloudFileClient(); - CloudFileShare snapshotRef = client.getShareReference(snapshot.name, snapshot.snapshotID); - assertTrue(snapshotRef.exists()); - assertTrue(snapshotRef.getMetadata().size() == 1 && snapshotRef.getMetadata().get("key1").equals("value1")); - - // verify that downloadAttributes() populates metadata - CloudFileShare snapshotRef2 = client.getShareReference(snapshot.name, snapshot.snapshotID); - snapshotRef2.downloadAttributes(); - snapshot.downloadAttributes(); - assertTrue(snapshotRef2.getMetadata().size() == 1 && snapshotRef2.getMetadata().get("key1").equals("value1")); - assertTrue(snapshot.getMetadata().size() == 1 && snapshot.getMetadata().get("key1").equals("value1")); - - // verify that exists() populates the metadata - CloudFileDirectory snapshotDir1 = snapshot.getRootDirectoryReference().getDirectoryReference("dir1"); - snapshotDir1.exists(); - assertTrue(snapshotDir1.getMetadata().size() == 1 && snapshotDir1.getMetadata().get("key2").equals("value2")); - - // verify that downloadAttributes() populates the metadata - CloudFileDirectory snapshotDir2 = snapshot.getRootDirectoryReference().getDirectoryReference("dir1"); - snapshotDir2.downloadAttributes(); - assertTrue(snapshotDir2.getMetadata().size() == 1 && snapshotDir2.getMetadata().get("key2").equals("value2")); - - // create snapshot with metadata - HashMap shareMeta2 = new HashMap(); - shareMeta2.put("abc", "def"); - CloudFileShare snapshotRef3 = this.share.createSnapshot(shareMeta2, null, null, null); - CloudFileShare snapshotRef4 = client.getShareReference(snapshotRef3.name, snapshotRef3.snapshotID); - assertTrue(snapshotRef4.exists()); - assertTrue(snapshotRef4.getMetadata().size() == 1 && snapshotRef4.getMetadata().get("abc").equals("def")); - - final UriQueryBuilder uriBuilder = new UriQueryBuilder(); - uriBuilder.add("sharesnapshot", snapshot.snapshotID); -// CloudFileShare snapshotRef5 = new CloudFileShare(uriBuilder.addToURI(this.share.getUri()), -// this.share.getServiceClient().getCredentials(), null); -// assertEquals(snapshot.snapshotID, snapshotRef5.snapshotID); -// assertTrue(snapshotRef5.exists()); - - snapshot.delete(); - } +// @Test +// public void testCreateShareSnapshot() throws StorageException, URISyntaxException, IOException { +// // create share with metadata +// this.share.create(); +// assertTrue(this.share.exists()); +// HashMap shareMeta = new HashMap(); +// shareMeta.put("key1", "value1"); +// this.share.setMetadata(shareMeta); +// this.share.uploadMetadata(); +// +// CloudFileDirectory dir1 = this.share.getRootDirectoryReference().getDirectoryReference("dir1"); +// dir1.create(); +// CloudFile file1 = dir1.getFileReference("file1"); +// file1.create(1024); +// ByteArrayInputStream srcStream = FileTestHelper.getRandomDataStream(1024); +// file1.upload(srcStream, 1024); +// +// // create directory with metadata +// HashMap dirMeta = new HashMap(); +// dirMeta.put("key2", "value2"); +// dir1.setMetadata(dirMeta); +// dir1.uploadMetadata(); +// +// // verify that exists() call on snapshot populates metadata +// CloudFileShare snapshot = this.share.createSnapshot(); +// CloudFileClient client = FileTestHelper.createCloudFileClient(); +// CloudFileShare snapshotRef = client.getShareReference(snapshot.name, snapshot.snapshotID); +// assertTrue(snapshotRef.exists()); +// assertTrue(snapshotRef.getMetadata().size() == 1 && snapshotRef.getMetadata().get("key1").equals("value1")); +// +// // verify that downloadAttributes() populates metadata +// CloudFileShare snapshotRef2 = client.getShareReference(snapshot.name, snapshot.snapshotID); +// snapshotRef2.downloadAttributes(); +// snapshot.downloadAttributes(); +// assertTrue(snapshotRef2.getMetadata().size() == 1 && snapshotRef2.getMetadata().get("key1").equals("value1")); +// assertTrue(snapshot.getMetadata().size() == 1 && snapshot.getMetadata().get("key1").equals("value1")); +// +// // verify that exists() populates the metadata +// CloudFileDirectory snapshotDir1 = snapshot.getRootDirectoryReference().getDirectoryReference("dir1"); +// snapshotDir1.exists(); +// assertTrue(snapshotDir1.getMetadata().size() == 1 && snapshotDir1.getMetadata().get("key2").equals("value2")); +// +// // verify that downloadAttributes() populates the metadata +// CloudFileDirectory snapshotDir2 = snapshot.getRootDirectoryReference().getDirectoryReference("dir1"); +// snapshotDir2.downloadAttributes(); +// assertTrue(snapshotDir2.getMetadata().size() == 1 && snapshotDir2.getMetadata().get("key2").equals("value2")); +// +// // create snapshot with metadata +// HashMap shareMeta2 = new HashMap(); +// shareMeta2.put("abc", "def"); +// CloudFileShare snapshotRef3 = this.share.createSnapshot(shareMeta2, null, null, null); +// CloudFileShare snapshotRef4 = client.getShareReference(snapshotRef3.name, snapshotRef3.snapshotID); +// assertTrue(snapshotRef4.exists()); +// assertTrue(snapshotRef4.getMetadata().size() == 1 && snapshotRef4.getMetadata().get("abc").equals("def")); +// +// final UriQueryBuilder uriBuilder = new UriQueryBuilder(); +// uriBuilder.add("sharesnapshot", snapshot.snapshotID); +//// CloudFileShare snapshotRef5 = new CloudFileShare(uriBuilder.addToURI(this.share.getUri()), +//// this.share.getServiceClient().getCredentials(), null); +//// assertEquals(snapshot.snapshotID, snapshotRef5.snapshotID); +//// assertTrue(snapshotRef5.exists()); +// +// snapshot.delete(); +// } - //@Test - public void testDeleteShareSnapshotOptions() throws StorageException, URISyntaxException, IOException { - // create share with metadata - this.share.create(); - assertTrue(this.share.exists()); - - // verify that exists() call on snapshot populates metadata - CloudFileShare snapshot = this.share.createSnapshot(); - CloudFileClient client = FileTestHelper.createCloudFileClient(); - CloudFileShare snapshotRef = client.getShareReference(snapshot.name, snapshot.snapshotID); - assertTrue(snapshotRef.exists()); - - try { - share.delete(); - } - catch (final StorageException e) { - assertEquals(StorageErrorCodeStrings.SHARE_HAS_SNAPSHOTS, e.getErrorCode()); - } - - share.delete(DeleteShareSnapshotsOption.INCLUDE_SNAPSHOTS, null, null, null); - assertFalse(share.exists()); - assertFalse(snapshot.exists()); - } - - //@Test - public void testListFilesAndDirectoriesWithinShareSnapshot() throws StorageException, URISyntaxException { - this.share.create(); - - CloudFileDirectory myDir = this.share.getRootDirectoryReference().getDirectoryReference("mydir"); - myDir.create(); - myDir.getFileReference("myfile").create(1024); - myDir.getDirectoryReference("yourDir").create(); - assertTrue(this.share.exists()); - - CloudFileShare snapshot = this.share.createSnapshot(); - CloudFileClient client = FileTestHelper.createCloudFileClient(); - CloudFileShare snapshotRef = client.getShareReference(snapshot.name, snapshot.snapshotID); - - Iterable listResult = snapshotRef.getRootDirectoryReference().listFilesAndDirectories(); - int count = 0; - for (ListFileItem listFileItem : listResult) { - count++; - assertEquals("mydir", ((CloudFileDirectory) listFileItem).getName()); - } - - assertEquals(1, count); - - count = 0; - listResult = snapshotRef.getRootDirectoryReference().getDirectoryReference("mydir").listFilesAndDirectories(); - for (ListFileItem listFileItem : listResult) { - if (listFileItem instanceof CloudFileDirectory) { - count++; - assertEquals("yourDir", ((CloudFileDirectory) listFileItem).getName()); - } - else { - count++; - assertEquals("myfile", ((CloudFile) listFileItem).getName()); - } - } - - assertEquals(2, count); - - snapshot.delete(); - } - - //@Test - public void testUnsupportedApisShareSnapshot() throws StorageException, URISyntaxException { - CloudFileClient client = FileTestHelper.createCloudFileClient(); - this.share.create(); - this.share.downloadPermissions(); - CloudFileShare snapshot = this.share.createSnapshot(); - try { - snapshot.createSnapshot(); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } +// @Test +// public void testDeleteShareSnapshotOptions() throws StorageException, URISyntaxException, IOException { +// // create share with metadata +// this.share.create(); +// assertTrue(this.share.exists()); +// +// // verify that exists() call on snapshot populates metadata +// CloudFileShare snapshot = this.share.createSnapshot(); +// CloudFileClient client = FileTestHelper.createCloudFileClient(); +// CloudFileShare snapshotRef = client.getShareReference(snapshot.name, snapshot.snapshotID); +// assertTrue(snapshotRef.exists()); +// +// try { +// share.delete(); +// } +// catch (final StorageException e) { +// assertEquals(StorageErrorCodeStrings.SHARE_HAS_SNAPSHOTS, e.getErrorCode()); +// } +// +// share.delete(DeleteShareSnapshotsOption.INCLUDE_SNAPSHOTS, null, null, null); +// assertFalse(share.exists()); +// assertFalse(snapshot.exists()); +// } + +// @Test +// public void testListFilesAndDirectoriesWithinShareSnapshot() throws StorageException, URISyntaxException { +// this.share.create(); +// +// CloudFileDirectory myDir = this.share.getRootDirectoryReference().getDirectoryReference("mydir"); +// myDir.create(); +// myDir.getFileReference("myfile").create(1024); +// myDir.getDirectoryReference("yourDir").create(); +// assertTrue(this.share.exists()); +// +// CloudFileShare snapshot = this.share.createSnapshot(); +// CloudFileClient client = FileTestHelper.createCloudFileClient(); +// CloudFileShare snapshotRef = client.getShareReference(snapshot.name, snapshot.snapshotID); +// +// Iterable listResult = snapshotRef.getRootDirectoryReference().listFilesAndDirectories(); +// int count = 0; +// for (ListFileItem listFileItem : listResult) { +// count++; +// assertEquals("mydir", ((CloudFileDirectory) listFileItem).getName()); +// } +// +// assertEquals(1, count); +// +// count = 0; +// listResult = snapshotRef.getRootDirectoryReference().getDirectoryReference("mydir").listFilesAndDirectories(); +// for (ListFileItem listFileItem : listResult) { +// if (listFileItem instanceof CloudFileDirectory) { +// count++; +// assertEquals("yourDir", ((CloudFileDirectory) listFileItem).getName()); +// } +// else { +// count++; +// assertEquals("myfile", ((CloudFile) listFileItem).getName()); +// } +// } +// +// assertEquals(2, count); +// +// snapshot.delete(); +// } + +// @Test +// public void testUnsupportedApisShareSnapshot() throws StorageException, URISyntaxException { +// CloudFileClient client = FileTestHelper.createCloudFileClient(); +// this.share.create(); +// this.share.downloadPermissions(); +// CloudFileShare snapshot = this.share.createSnapshot(); // try { -// new CloudFileShare(snapshot.getQualifiedUri(), client.getCredentials(), "2016-10-24T16:37:17.0000000Z"); +// snapshot.createSnapshot(); // fail("Shouldn't get here"); // } // catch (IllegalArgumentException e) { -// assertEquals(SR.SNAPSHOT_QUERY_OPTION_ALREADY_DEFINED, e.getMessage()); +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); // } - try { - snapshot.downloadPermissions(); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - snapshot.getStats(); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - snapshot.uploadMetadata(); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - FileSharePermissions permissions = new FileSharePermissions(); - snapshot.uploadPermissions(permissions); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - snapshot.uploadProperties(); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - - snapshot.delete(); - } +//// try { +//// new CloudFileShare(snapshot.getQualifiedUri(), client.getCredentials(), "2016-10-24T16:37:17.0000000Z"); +//// fail("Shouldn't get here"); +//// } +//// catch (IllegalArgumentException e) { +//// assertEquals(SR.SNAPSHOT_QUERY_OPTION_ALREADY_DEFINED, e.getMessage()); +//// } +// try { +// snapshot.downloadPermissions(); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// snapshot.getStats(); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// snapshot.uploadMetadata(); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// FileSharePermissions permissions = new FileSharePermissions(); +// snapshot.uploadPermissions(permissions); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// snapshot.uploadProperties(); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// +// snapshot.delete(); +// } private static void assertPermissionsEqual(FileSharePermissions expected, FileSharePermissions actual) { HashMap expectedPolicies = expected.getSharedAccessPolicies(); diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java index f15c20b4a..f47374359 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/file/CloudFileTests.java @@ -1617,103 +1617,103 @@ private void doCloudFileCopy(boolean sourceIsSas, boolean destinationIsSas) source.delete(); } - //@Test - public void testUnsupportedFileApisWithinShareSnapshot() throws StorageException, URISyntaxException { - CloudFileShare snapshot = this.share.createSnapshot(); - CloudFile file = snapshot.getRootDirectoryReference().getFileReference("file"); - - try { - file.create(1024); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - file.delete(); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - file.uploadMetadata(); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - file.abortCopy(null); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - file.clearRange(0, 512); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - file.startCopy(file); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } - try { - file.upload(null, 512); - fail("Shouldn't get here"); - } - catch (IllegalArgumentException e) { - assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); - } catch (IOException e) { - fail("Shouldn't get here"); - } - - snapshot.delete(); - } - - //@Test - public void testSupportedFileApisInShareSnapshot() throws StorageException, URISyntaxException, UnsupportedEncodingException { - CloudFileDirectory dir = this.share.getRootDirectoryReference().getDirectoryReference("dir1"); - dir.deleteIfExists(); - dir.create(); - CloudFile file = dir.getFileReference("file"); - file.create(1024); - - HashMap meta = new HashMap(); - meta.put("key1", "value1"); - file.setMetadata(meta); - file.uploadMetadata(); - - CloudFileShare snapshot = this.share.createSnapshot(); - CloudFile snapshotFile = snapshot.getRootDirectoryReference() - .getDirectoryReference("dir1").getFileReference("file"); - - HashMap meta2 = new HashMap(); - meta2.put("key2", "value2"); - file.setMetadata(meta2); - file.uploadMetadata(); - snapshotFile.downloadAttributes(); - - assertTrue(snapshotFile.getMetadata().size() == 1 && snapshotFile.getMetadata().get("key1").equals("value1")); - assertNotNull(snapshotFile.getProperties().getEtag()); - - file.downloadAttributes(); - assertTrue(file.getMetadata().size() == 1 && file.getMetadata().get("key2").equals("value2")); - assertNotNull(file.getProperties().getEtag()); - assertNotEquals(file.getProperties().getEtag(), snapshotFile.getProperties().getEtag()); - - final UriQueryBuilder uriBuilder = new UriQueryBuilder(); - uriBuilder.add("sharesnapshot", snapshot.snapshotID); - CloudFile snapshotFile2 = new CloudFile(uriBuilder.addToURI(file.getUri()), this.share.getServiceClient().getCredentials()); - assertEquals(snapshot.snapshotID, snapshotFile2.getShare().snapshotID); - assertTrue(snapshotFile2.exists()); - - snapshot.delete(); - } +// @Test +// public void testUnsupportedFileApisWithinShareSnapshot() throws StorageException, URISyntaxException { +// CloudFileShare snapshot = this.share.createSnapshot(); +// CloudFile file = snapshot.getRootDirectoryReference().getFileReference("file"); +// +// try { +// file.create(1024); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// file.delete(); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// file.uploadMetadata(); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// file.abortCopy(null); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// file.clearRange(0, 512); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// file.startCopy(file); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } +// try { +// file.upload(null, 512); +// fail("Shouldn't get here"); +// } +// catch (IllegalArgumentException e) { +// assertEquals(SR.INVALID_OPERATION_FOR_A_SHARE_SNAPSHOT, e.getMessage()); +// } catch (IOException e) { +// fail("Shouldn't get here"); +// } +// +// snapshot.delete(); +// } + +// @Test +// public void testSupportedFileApisInShareSnapshot() throws StorageException, URISyntaxException, UnsupportedEncodingException { +// CloudFileDirectory dir = this.share.getRootDirectoryReference().getDirectoryReference("dir1"); +// dir.deleteIfExists(); +// dir.create(); +// CloudFile file = dir.getFileReference("file"); +// file.create(1024); +// +// HashMap meta = new HashMap(); +// meta.put("key1", "value1"); +// file.setMetadata(meta); +// file.uploadMetadata(); +// +// CloudFileShare snapshot = this.share.createSnapshot(); +// CloudFile snapshotFile = snapshot.getRootDirectoryReference() +// .getDirectoryReference("dir1").getFileReference("file"); +// +// HashMap meta2 = new HashMap(); +// meta2.put("key2", "value2"); +// file.setMetadata(meta2); +// file.uploadMetadata(); +// snapshotFile.downloadAttributes(); +// +// assertTrue(snapshotFile.getMetadata().size() == 1 && snapshotFile.getMetadata().get("key1").equals("value1")); +// assertNotNull(snapshotFile.getProperties().getEtag()); +// +// file.downloadAttributes(); +// assertTrue(file.getMetadata().size() == 1 && file.getMetadata().get("key2").equals("value2")); +// assertNotNull(file.getProperties().getEtag()); +// assertNotEquals(file.getProperties().getEtag(), snapshotFile.getProperties().getEtag()); +// +// final UriQueryBuilder uriBuilder = new UriQueryBuilder(); +// uriBuilder.add("sharesnapshot", snapshot.snapshotID); +// CloudFile snapshotFile2 = new CloudFile(uriBuilder.addToURI(file.getUri()), this.share.getServiceClient().getCredentials()); +// assertEquals(snapshot.snapshotID, snapshotFile2.getShare().snapshotID); +// assertTrue(snapshotFile2.exists()); +// +// snapshot.delete(); +// } } \ No newline at end of file diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileClient.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileClient.java index 409d4ff27..4b3fb37af 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileClient.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileClient.java @@ -101,30 +101,30 @@ public CloudFileClient(StorageUri storageUri, StorageCredentials credentials) { */ public CloudFileShare getShareReference(final String shareName) throws URISyntaxException, StorageException { Utility.assertNotNullOrEmpty("shareName", shareName); - return this.getShareReference(shareName, null); + return new CloudFileShare(shareName, this); } - /** - * Gets a {@link CloudFileShare} object with the specified name. - * - * @param shareName - * The name of the share, which must adhere to share naming rules. The share name should not - * include any path separator characters (/). - * Share names must be lowercase, between 3-63 characters long and must start with a letter or - * number. Share names may contain only letters, numbers, and the dash (-) character. - * @param snapshotID - * A String that represents the snapshot ID of the share. - * @return A reference to a {@link CloudFileShare} object. - * @throws StorageException - * @throws URISyntaxException - * - * @see Naming and Referencing Shares, - * Directories, Files, and Metadata - */ - protected CloudFileShare getShareReference(final String shareName, String snapshotID) throws URISyntaxException, StorageException { - Utility.assertNotNullOrEmpty("shareName", shareName); - return new CloudFileShare(shareName, snapshotID, this); - } +// /** +// * Gets a {@link CloudFileShare} object with the specified name. +// * +// * @param shareName +// * The name of the share, which must adhere to share naming rules. The share name should not +// * include any path separator characters (/). +// * Share names must be lowercase, between 3-63 characters long and must start with a letter or +// * number. Share names may contain only letters, numbers, and the dash (-) character. +// * @param snapshotID +// * A String that represents the snapshot ID of the share. +// * @return A reference to a {@link CloudFileShare} object. +// * @throws StorageException +// * @throws URISyntaxException +// * +// * @see Naming and Referencing Shares, +// * Directories, Files, and Metadata +// */ +// protected CloudFileShare getShareReference(final String shareName, String snapshotID) throws URISyntaxException, StorageException { +// Utility.assertNotNullOrEmpty("shareName", shareName); +// return new CloudFileShare(shareName, snapshotID, this); +// } /** * Returns an enumerable collection of shares for this File service client. diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java index 28b9904c0..20b618ccb 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/CloudFileShare.java @@ -81,7 +81,7 @@ public final class CloudFileShare { /** * Holds the snapshot ID. */ - String snapshotID; + //String snapshotID; /** * Holds a reference to the associated service client. @@ -111,14 +111,14 @@ public final class CloudFileShare { * @see Naming and Referencing Shares, * Directories, Files, and Metadata */ - protected CloudFileShare(final String shareName, String snapshotID, final CloudFileClient client) throws URISyntaxException, + protected CloudFileShare(final String shareName, /*String snapshotID,*/ final CloudFileClient client) throws URISyntaxException, StorageException { Utility.assertNotNull("client", client); Utility.assertNotNull("shareName", shareName); this.storageUri = PathUtility.appendPathToUri(client.getStorageUri(), shareName); this.name = shareName; - this.snapshotID = snapshotID; + //this.snapshotID = snapshotID; this.fileServiceClient = client; } @@ -717,135 +717,135 @@ public FileSharePermissions postProcessResponse(HttpURLConnection connection, return getRequest; } - /** - * Creates a snapshot of the share. - * - * @return A CloudFileShare object that represents the snapshot of the share. - * - * @throws StorageException - * If a storage service error occurred. - */ - @DoesServiceRequest - protected final CloudFileShare createSnapshot() throws StorageException { - return this - .createSnapshot(null /* metadata */, null /* accessCondition */, null /* options */, null /* opContext */); - } - - /** - * Creates a snapshot of the file share using the specified request options and operation context. - * - * @param accessCondition - * An {@link AccessCondition} object that represents the access conditions for the share. - * @param options - * A {@link FileRequestOptions} object that specifies any additional options for the request. Specifying - * null will use the default request options from the associated service client ( - * {@link CloudFileClient}). - * @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 CloudFileShare object that represents the snapshot of the file share. - * - * @throws StorageException - * If a storage service error occurred. - */ - @DoesServiceRequest - protected final CloudFileShare createSnapshot(final AccessCondition accessCondition, FileRequestOptions options, - OperationContext opContext) throws StorageException { - return this.createSnapshot(null /* metadata */, accessCondition, options, opContext); - } - - /** - * Creates a snapshot of the file share using the specified request options and operation context. - * - * @param metadata - * A collection of name-value pairs defining the metadata of the snapshot, or null. - * @param accessCondition - * An {@link AccessCondition} object that represents the access conditions for the file share. - * @param options - * A {@link FileRequestOptions} object that specifies any additional options for the request. Specifying - * null will use the default request options from the associated service client ( - * {@link CloudFileClient}). - * @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 CloudFileShare object that represents the snapshot of the file share. - * - * @throws StorageException - * If a storage service error occurred. - */ - @DoesServiceRequest - protected final CloudFileShare createSnapshot(final HashMap metadata, - final AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) - throws StorageException { - //assertNoSnapshot(); - - if (opContext == null) { - opContext = new OperationContext(); - } - - opContext.initialize(); - options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); - - return ExecutionEngine - .executeWithRetry(this.fileServiceClient, this, - this.createSnapshotImpl(metadata, accessCondition, options), options.getRetryPolicyFactory(), - opContext); - } - - private StorageRequest createSnapshotImpl( - final HashMap metadata, final AccessCondition accessCondition, - final FileRequestOptions options) { - final StorageRequest putRequest = - new StorageRequest( - options, this.getStorageUri()) { - - @Override - public HttpURLConnection buildRequest(CloudFileClient client, CloudFileShare share, OperationContext context) - throws Exception { - return FileRequest.snapshotShare(share.getTransformedAddress().getUri(this.getCurrentLocation()), - options, context, accessCondition); - } - - @Override - public void setHeaders(HttpURLConnection connection, CloudFileShare share, OperationContext context) { - if (metadata != null) { - FileRequest.addMetadata(connection, metadata, context); - } - } - - @Override - public void signRequest(HttpURLConnection connection, CloudFileClient client, OperationContext context) - throws Exception { - StorageRequest.signBlobQueueAndFileRequest(connection, client, 0L, context); - } - - @Override - public CloudFileShare preProcessResponse(CloudFileShare share, CloudFileClient client, OperationContext context) - throws Exception { - if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { - this.setNonExceptionedRetryableFailure(true); - return null; - } - - final String snapshotTime = FileResponse.getSnapshotTime(this.getConnection()); - CloudFileShare snapshot = new CloudFileShare(share.getName(), snapshotTime, client); - snapshot.setProperties(new FileShareProperties(share.properties)); - - // use the specified metadata if not null : otherwise share's metadata - snapshot.setMetadata(metadata != null ? metadata : share.metadata); - - snapshot.updatePropertiesFromResponse(this.getConnection()); - - return snapshot; - } - }; +// /** +// * Creates a snapshot of the share. +// * +// * @return A CloudFileShare object that represents the snapshot of the share. +// * +// * @throws StorageException +// * If a storage service error occurred. +// */ +// @DoesServiceRequest +// protected final CloudFileShare createSnapshot() throws StorageException { +// return this +// .createSnapshot(null /* metadata */, null /* accessCondition */, null /* options */, null /* opContext */); +// } +// +// /** +// * Creates a snapshot of the file share using the specified request options and operation context. +// * +// * @param accessCondition +// * An {@link AccessCondition} object that represents the access conditions for the share. +// * @param options +// * A {@link FileRequestOptions} object that specifies any additional options for the request. Specifying +// * null will use the default request options from the associated service client ( +// * {@link CloudFileClient}). +// * @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 CloudFileShare object that represents the snapshot of the file share. +// * +// * @throws StorageException +// * If a storage service error occurred. +// */ +// @DoesServiceRequest +// protected final CloudFileShare createSnapshot(final AccessCondition accessCondition, FileRequestOptions options, +// OperationContext opContext) throws StorageException { +// return this.createSnapshot(null /* metadata */, accessCondition, options, opContext); +// } +// +// /** +// * Creates a snapshot of the file share using the specified request options and operation context. +// * +// * @param metadata +// * A collection of name-value pairs defining the metadata of the snapshot, or null. +// * @param accessCondition +// * An {@link AccessCondition} object that represents the access conditions for the file share. +// * @param options +// * A {@link FileRequestOptions} object that specifies any additional options for the request. Specifying +// * null will use the default request options from the associated service client ( +// * {@link CloudFileClient}). +// * @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 CloudFileShare object that represents the snapshot of the file share. +// * +// * @throws StorageException +// * If a storage service error occurred. +// */ +// @DoesServiceRequest +// protected final CloudFileShare createSnapshot(final HashMap metadata, +// final AccessCondition accessCondition, FileRequestOptions options, OperationContext opContext) +// throws StorageException { +// //assertNoSnapshot(); +// +// if (opContext == null) { +// opContext = new OperationContext(); +// } +// +// opContext.initialize(); +// options = FileRequestOptions.populateAndApplyDefaults(options, this.fileServiceClient); +// +// return ExecutionEngine +// .executeWithRetry(this.fileServiceClient, this, +// this.createSnapshotImpl(metadata, accessCondition, options), options.getRetryPolicyFactory(), +// opContext); +// } - return putRequest; - } +// private StorageRequest createSnapshotImpl( +// final HashMap metadata, final AccessCondition accessCondition, +// final FileRequestOptions options) { +// final StorageRequest putRequest = +// new StorageRequest( +// options, this.getStorageUri()) { +// +// @Override +// public HttpURLConnection buildRequest(CloudFileClient client, CloudFileShare share, OperationContext context) +// throws Exception { +// return FileRequest.snapshotShare(share.getTransformedAddress().getUri(this.getCurrentLocation()), +// options, context, accessCondition); +// } +// +// @Override +// public void setHeaders(HttpURLConnection connection, CloudFileShare share, OperationContext context) { +// if (metadata != null) { +// FileRequest.addMetadata(connection, metadata, context); +// } +// } +// +// @Override +// public void signRequest(HttpURLConnection connection, CloudFileClient client, OperationContext context) +// throws Exception { +// StorageRequest.signBlobQueueAndFileRequest(connection, client, 0L, context); +// } +// +// @Override +// public CloudFileShare preProcessResponse(CloudFileShare share, CloudFileClient client, OperationContext context) +// throws Exception { +// if (this.getResult().getStatusCode() != HttpURLConnection.HTTP_CREATED) { +// this.setNonExceptionedRetryableFailure(true); +// return null; +// } +// +// final String snapshotTime = FileResponse.getSnapshotTime(this.getConnection()); +// CloudFileShare snapshot = new CloudFileShare(share.getName(), snapshotTime, client); +// snapshot.setProperties(new FileShareProperties(share.properties)); +// +// // use the specified metadata if not null : otherwise share's metadata +// snapshot.setMetadata(metadata != null ? metadata : share.metadata); +// +// snapshot.updatePropertiesFromResponse(this.getConnection()); +// +// return snapshot; +// } +// }; +// +// return putRequest; +// } /** * Queries the service for this share's {@link ShareStats}. @@ -1452,12 +1452,12 @@ private void parseQueryAndVerify(final StorageUri completeUri, final StorageCred this.storageUri = PathUtility.stripURIQueryAndFragment(completeUri); - final HashMap queryParameters = PathUtility.parseQueryString(completeUri.getQuery()); +// final HashMap queryParameters = PathUtility.parseQueryString(completeUri.getQuery()); - final String[] snapshotIDs = queryParameters.get(Constants.QueryConstants.SHARE_SNAPSHOT); - if (snapshotIDs != null && snapshotIDs.length > 0) { - this.snapshotID = snapshotIDs[0]; - } +// final String[] snapshotIDs = queryParameters.get(Constants.QueryConstants.SHARE_SNAPSHOT); +// if (snapshotIDs != null && snapshotIDs.length > 0) { +// this.snapshotID = snapshotIDs[0]; +// } final StorageCredentialsSharedAccessSignature parsedCredentials = SharedAccessSignatureHelper.parseQuery(completeUri); @@ -1495,25 +1495,25 @@ public URI getUri() { return this.storageUri.getPrimaryUri(); } - /** - * Returns the snapshotID for this share. - * - * @return The snapshotID as a string for this share. - */ - protected final String getSnapshot() { - return this.snapshotID; - } - - /** - * Indicates whether this share is a snapshot. - * - * @return true if the share is a snapshot, otherwise false. - * - * @see DeleteSnapshotsOption - */ - protected final boolean isSnapshot() { - return this.snapshotID != null; - } +// /** +// * Returns the snapshotID for this share. +// * +// * @return The snapshotID as a string for this share. +// */ +// protected final String getSnapshot() { +// return this.snapshotID; +// } +// +// /** +// * Indicates whether this share is a snapshot. +// * +// * @return true if the share is a snapshot, otherwise false. +// * +// * @see DeleteSnapshotsOption +// */ +// protected final boolean isSnapshot() { +// return this.snapshotID != null; +// } /** * Returns the list of URIs for all locations. @@ -1524,23 +1524,23 @@ public StorageUri getStorageUri() { return this.storageUri; } - /** - * Returns the snapshot or shared access signature qualified URI for this share. - * - * @return A java.net.URI object that represents the snapshot or shared access signature. - * - * @throws StorageException - * If a storage service error occurred. - * @throws URISyntaxException - * If the resource URI is invalid. - */ - public final URI getQualifiedUri() throws URISyntaxException, StorageException { - if (this.isSnapshot()) { - return PathUtility.addToQuery(this.getUri(), String.format("sharesnapshot=%s", this.snapshotID)); - } - - return this.fileServiceClient.getCredentials().transformUri(this.getUri()); - } +// /** +// * Returns the snapshot or shared access signature qualified URI for this share. +// * +// * @return A java.net.URI object that represents the snapshot or shared access signature. +// * +// * @throws StorageException +// * If a storage service error occurred. +// * @throws URISyntaxException +// * If the resource URI is invalid. +// */ +// public final URI getQualifiedUri() throws URISyntaxException, StorageException { +// if (this.isSnapshot()) { +// return PathUtility.addToQuery(this.getUri(), String.format("sharesnapshot=%s", this.snapshotID)); +// } +// +// return this.fileServiceClient.getCredentials().transformUri(this.getUri()); +// } /** * Returns the name of the share. diff --git a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListHandler.java b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListHandler.java index 3d3b9b99f..0721d15e7 100644 --- a/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListHandler.java +++ b/microsoft-azure-storage/src/com/microsoft/azure/storage/file/ShareListHandler.java @@ -107,7 +107,7 @@ public void endElement(String uri, String localName, String qName) throws SAXExc CloudFileShare retShare = this.serviceClient.getShareReference(this.shareName); retShare.setMetadata(this.attributes.getMetadata()); retShare.setProperties(this.attributes.getProperties()); - retShare.snapshotID = this.snapshotID; + //retShare.snapshotID = this.snapshotID; this.response.getResults().add(retShare); } From a95f7d79392147d9d11e3e50bffcd4c2e3e50938 Mon Sep 17 00:00:00 2001 From: Josh Friedman Date: Mon, 22 May 2017 16:34:46 -0700 Subject: [PATCH 7/8] Fix failing test which relied on small put blob size --- .../com/microsoft/azure/storage/MaximumExecutionTimeTests.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/MaximumExecutionTimeTests.java b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/MaximumExecutionTimeTests.java index d1a8ef1c0..2335f910a 100644 --- a/microsoft-azure-storage-test/src/com/microsoft/azure/storage/MaximumExecutionTimeTests.java +++ b/microsoft-azure-storage-test/src/com/microsoft/azure/storage/MaximumExecutionTimeTests.java @@ -191,6 +191,9 @@ public void testMaximumExecutionTimeBlobWrites() throws URISyntaxException, Stor BlobRequestOptions options = new BlobRequestOptions(); options.setMaximumExecutionTimeInMs(5000); + // set a lower put blob threshold so that we perform multiple put block requests that timeout + options.setSingleBlobPutThresholdInBytes(32 * Constants.MB); + CloudBlobClient blobClient = TestHelper.createCloudBlobClient(); CloudBlobContainer container = blobClient.getContainerReference(generateRandomName("container")); From 25b7fef47531cda20ce53d67646888c531b4bd86 Mon Sep 17 00:00:00 2001 From: Josh Friedman Date: Mon, 22 May 2017 17:26:15 -0700 Subject: [PATCH 8/8] Update date on changelog --- ChangeLog.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ChangeLog.txt b/ChangeLog.txt index f7b66cd7c..67632a99d 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -1,4 +1,4 @@ -2017.05.15 Version 5.2.0 +2017.05.23 Version 5.2.0 * Fixed Exists() calls on Shares and Directories to now populate metadata. This was already being done for Files. * Changed blob constants to support up to 256 MB on put blob for block blobs. The default value for put blob threshold has also been updated to half of the maximum, or 128 MB currently. * Fixed a bug that prevented setting content MD5 to true when creating a new file.