Skip to content
This repository was archived by the owner on Jul 19, 2024. It is now read-only.

Commit 11410dc

Browse files
committed
Merge pull request #32 from pemari-msft/master
Java Storage Client Library 2.0.0
2 parents 56ffe10 + 6cd884e commit 11410dc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1229
-347
lines changed

BreakingChanges.txt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
Changes in 2.0.0
2+
3+
BLOB
4+
* Deprecated getSubDirectoryReference(). Use getDirectoryReference() instead.
5+
6+
TABLE
7+
* Loses millisecond precision when reading Date values on Table Entities written using versions of this library prior to 2.0.0, unless TableRequestOptions.dateBackwardCompatibility is set to true. See http://go.microsoft.com/fwlink/?LinkId=523753 for more details.
8+
9+
FILE
10+
* Deprecated getSubDirectoryReference(). Use getDirectoryReference() instead.
11+
12+
OTHER
13+
* Changed maxResults arguments of List*Segmented() methods to type Integer instead of int
14+
* Added validation to ensure that the maxResults arguments of List*Segmented() methods are positive when non-null
15+
* Added PARAMETER_SHOULD_BE_GREATER_OR_EQUAL attribute to SR which is used by Utility.assertGreaterThanOrEqual()
16+
* Deprecated AuthenticationScheme and its getter and setter. In the future only SharedKey will be used.
17+
118
Changes in 0.7.0
219

320
BLOB

ChangeLog.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
2014.12.20 Version 2.0.0
2+
* Deprecated getSubDirectoryReference() for blob directories and file directories. Use getDirectoryReference() instead.
3+
* Fixed a bug where maxResults was not verified to be positive for list operations.
4+
* Fixed a bug where high precision Date values stored on Table Entites were forced to fit into milliseconds resulting in inaccuracies. Precision is limited to 1 millisecond by Java.util.Date. If greater precision is required, the String should be used directly.
5+
* Added TableRequestOptions.dateBackwardCompatibility, which supports reading Date values on Table Entities written using versions of this library prior to 2.0.0. See http://go.microsoft.com/fwlink/?LinkId=523753 for more details.
6+
* Deprecated AuthenticationScheme and its getter and setter. In the future only SharedKey will be used.
7+
18
2014.11.03 Version 1.3.1
29
* Reverted timestamp bug fix from 1.3.0 for further consideration.
310

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ To get the binaries of this library as distributed by Microsoft, ready for use w
2828
<dependency>
2929
<groupId>com.microsoft.azure</groupId>
3030
<artifactId>azure-storage</artifactId>
31-
<version>1.3.1</version>
31+
<version>2.0.0</version>
3232
</dependency>
3333
```
3434

microsoft-azure-storage-samples/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<dependency>
2626
<groupId>com.microsoft.azure</groupId>
2727
<artifactId>azure-storage</artifactId>
28-
<version>1.3.1</version>
28+
<version>2.0.0</version>
2929
</dependency>
3030
</dependencies>
3131
</project>

microsoft-azure-storage-test/src/com/microsoft/azure/storage/GenericTests.java

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@
2020
import java.io.IOException;
2121
import java.net.HttpURLConnection;
2222
import java.net.URISyntaxException;
23+
import java.text.ParseException;
24+
import java.text.SimpleDateFormat;
2325
import java.util.ArrayList;
26+
import java.util.Date;
2427
import java.util.HashMap;
2528
import java.util.UUID;
2629

@@ -414,6 +417,128 @@ public void testMaximumExecutionTimeBlobByteArray() throws URISyntaxException, S
414417
}
415418
}
416419

420+
@Test
421+
public void testDateStringParsingWithRounding() throws ParseException {
422+
String fullDateString = "1999-12-31T23:59:45.1234567Z";
423+
SimpleDateFormat testFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS Z");
424+
Date milliDate = testFormat.parse("1999-12-31T23:59:45.123 -0000");
425+
assertEquals(milliDate, Utility.parseDate(fullDateString));
426+
427+
fullDateString = "1999-04-30T23:59:55.9876Z";
428+
long millisSinceEpoch = 925516795987L;
429+
430+
Date deciDate = Utility.parseDate(fullDateString.replace("876Z", "Z"));
431+
assertEquals(deciDate.getTime(), (millisSinceEpoch / 100) * 100);
432+
433+
Date centiDate = Utility.parseDate(fullDateString.replace("76Z", "Z"));
434+
assertEquals(centiDate.getTime(), (millisSinceEpoch / 10) * 10);
435+
436+
milliDate = Utility.parseDate(fullDateString);
437+
assertEquals(milliDate.getTime(), millisSinceEpoch);
438+
}
439+
440+
@Test
441+
public void testDateStringParsing() throws ParseException {
442+
// 2014-12-07T09:15:12.123Z from Java
443+
testDate("2014-12-07T09:15:12.123Z", 1417943712123L, 0, false, false);
444+
445+
// 2015-01-14T14:53:32.800Z from Java
446+
testDate("2015-01-14T14:53:32.800Z", 1421247212800L, 0, false, false);
447+
448+
// 2014-11-29T22:55:21.9876543Z from .Net
449+
testDate("2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, false, false);
450+
451+
// 2015-02-14T03:11:13.0000229Z from .Net
452+
testDate("2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, false, false);
453+
}
454+
455+
@Test
456+
public void testDateStringParsingCrossVersion() throws ParseException {
457+
// 2014-12-07T09:15:12.123Z from Java, milliseconds are incorrectly left-padded
458+
testDate("2014-12-07T09:15:12.0000123Z", 1417943712123L, 0, true, false);
459+
460+
// 2015-01-14T14:53:32.800Z from Java, milliseconds are incorrectly left-padded
461+
testDate("2015-01-14T14:53:32.0000800Z", 1421247212800L, 0, true, false);
462+
463+
// 2014-11-29T22:55:21.9876543Z from .Net
464+
testDate("2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, true, false);
465+
466+
// 2015-02-14T03:11:13.0000229Z from .Net
467+
testDate("2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, true, false);
468+
}
469+
470+
@Test
471+
public void testDateStringParsingWithBackwardCompatibility() throws ParseException {
472+
// 2014-12-07T09:15:12.123Z from Java
473+
testDate("2014-12-07T09:15:12.123Z", 1417943712123L, 0, false, true);
474+
475+
// 2015-01-14T14:53:32.800Z from Java
476+
testDate("2015-01-14T14:53:32.800Z", 1421247212800L, 0, false, true);
477+
478+
// 2014-11-29T22:55:21.9876543Z from .Net
479+
testDate("2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, false, true);
480+
481+
// 2015-02-14T03:11:13.0000229Z from .Net
482+
testDate("2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, false, true);
483+
}
484+
485+
@Test
486+
public void testDateStringParsingCrossVersionWithBackwardCompatibility() throws ParseException {
487+
// 2014-12-07T09:15:12.123Z from Java, milliseconds are incorrectly left-padded
488+
testDate("2014-12-07T09:15:12.0000123Z", 1417943712123L, 0, true, true);
489+
490+
// 2015-01-14T14:53:32.800Z from Java, milliseconds are incorrectly left-padded
491+
testDate("2015-01-14T14:53:32.0000800Z", 1421247212800L, 0, true, true);
492+
493+
// 2014-11-29T22:55:21.9876543Z from .Net
494+
testDate("2014-11-29T22:55:21.9876543Z", 1417301721987L, 6543, true, true);
495+
496+
// 2015-02-14T03:11:13.0000229Z from .Net
497+
testDate("2015-02-14T03:11:13.0000229Z", 1423883473000L, 229, true, true);
498+
}
499+
500+
private static void testDate(final String dateString, final long intendedMilliseconds, final int ticks,
501+
final boolean writtenPre2, final boolean dateBackwardCompatibility) {
502+
assertTrue(ticks >= 0); // ticks is non-negative
503+
assertTrue(ticks <= 9999); // ticks do not overflow into milliseconds
504+
long expectedMilliseconds = intendedMilliseconds;
505+
506+
if (dateBackwardCompatibility && (intendedMilliseconds % 1000 == 0) && (ticks < 1000)) {
507+
// when no milliseconds are present dateBackwardCompatibility causes up to 3 digits of ticks
508+
// to be read as milliseconds
509+
expectedMilliseconds += ticks;
510+
} else if (writtenPre2 && !dateBackwardCompatibility && (ticks == 0)) {
511+
// without DateBackwardCompatibility, milliseconds stored by Java prior to 2.0.0 are lost
512+
expectedMilliseconds -= expectedMilliseconds % 1000;
513+
}
514+
515+
assertEquals(expectedMilliseconds, Utility.parseDate(dateString, dateBackwardCompatibility).getTime());
516+
}
517+
518+
@Test
519+
public void testDateStringFormatting() {
520+
String fullDateString = "2014-12-07T09:15:12.123Z";
521+
String outDateString = Utility.getJavaISO8601Time(Utility.parseDate(fullDateString));
522+
assertEquals(fullDateString, outDateString);
523+
524+
fullDateString = "2015-01-14T14:53:32.800Z";
525+
outDateString = Utility.getJavaISO8601Time(Utility.parseDate(fullDateString));
526+
assertEquals(fullDateString, outDateString);
527+
528+
// Ensure that trimming of trailing zeroes by the service does not affect this
529+
fullDateString = "2015-01-14T14:53:32.8Z";
530+
outDateString = Utility.getJavaISO8601Time(Utility.parseDate(fullDateString));
531+
fullDateString = fullDateString.replace("Z", "00Z");
532+
assertEquals(fullDateString, outDateString);
533+
534+
// Ensure that trimming of trailing zeroes by the service does not affect this
535+
// even with dateBackwardCompatibility
536+
fullDateString = "2015-01-14T14:53:32.0000800Z";
537+
outDateString = Utility.getJavaISO8601Time(Utility.parseDate(fullDateString, true));
538+
fullDateString = "2015-01-14T14:53:32.800Z";
539+
assertEquals(fullDateString, outDateString);
540+
}
541+
417542
private static String generateRandomContainerName() {
418543
String containerName = "container" + UUID.randomUUID().toString();
419544
return containerName.replace("-", "");

microsoft-azure-storage-test/src/com/microsoft/azure/storage/StorageUriTests.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ public void testBlobTypesWithStorageUri() throws StorageException, URISyntaxExce
211211
assertEquals(containerUri, directory.getContainer().getStorageUri());
212212
assertEquals(endpoint, directory.getServiceClient().getStorageUri());
213213

214-
CloudBlobDirectory subdirectory = directory.getSubDirectoryReference("subdirectory");
214+
CloudBlobDirectory subdirectory = directory.getDirectoryReference("subdirectory");
215215
assertEquals(subdirectoryUri, subdirectory.getStorageUri());
216216
assertEquals(subdirectoryUri.getPrimaryUri(), subdirectory.getUri());
217217
assertEquals(directoryUri, subdirectory.getParent().getStorageUri());

microsoft-azure-storage-test/src/com/microsoft/azure/storage/TestHelper.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,28 +46,33 @@ public class TestHelper {
4646
private static StorageCredentialsAccountAndKey credentials;
4747
private static CloudStorageAccount account;
4848

49+
@SuppressWarnings("deprecation")
4950
private final static AuthenticationScheme defaultAuthenticationScheme = AuthenticationScheme.SHAREDKEYFULL;
5051
private final static boolean enableFiddler = true;
5152
private final static boolean requireSecondaryEndpoint = false;
5253

54+
@SuppressWarnings("deprecation")
5355
public static CloudBlobClient createCloudBlobClient() throws StorageException {
5456
CloudBlobClient client = getAccount().createCloudBlobClient();
5557
client.setAuthenticationScheme(defaultAuthenticationScheme);
5658
return client;
5759
}
5860

61+
@SuppressWarnings("deprecation")
5962
public static CloudFileClient createCloudFileClient() throws StorageException {
6063
CloudFileClient client = getAccount().createCloudFileClient();
6164
client.setAuthenticationScheme(defaultAuthenticationScheme);
6265
return client;
6366
}
6467

68+
@SuppressWarnings("deprecation")
6569
public static CloudQueueClient createCloudQueueClient() throws StorageException {
6670
CloudQueueClient client = getAccount().createCloudQueueClient();
6771
client.setAuthenticationScheme(defaultAuthenticationScheme);
6872
return client;
6973
}
7074

75+
@SuppressWarnings("deprecation")
7176
public static CloudTableClient createCloudTableClient() throws StorageException {
7277
CloudTableClient client = getAccount().createCloudTableClient();
7378
client.setAuthenticationScheme(defaultAuthenticationScheme);

microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobClientTests.java

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import com.microsoft.azure.storage.TestRunners.CloudTests;
3636
import com.microsoft.azure.storage.TestRunners.DevFabricTests;
3737
import com.microsoft.azure.storage.TestRunners.DevStoreTests;
38+
import com.microsoft.azure.storage.core.SR;
3839

3940
/**
4041
* Blob Client Tests
@@ -47,7 +48,7 @@ public class CloudBlobClientTests {
4748
*/
4849
@Test
4950
@Category({ DevFabricTests.class, DevStoreTests.class, CloudTests.class })
50-
public void testListContainersTest() throws StorageException, URISyntaxException {
51+
public void testListContainers() throws StorageException, URISyntaxException {
5152
CloudBlobClient bClient = BlobTestHelper.createCloudBlobClient();
5253
ArrayList<String> containerList = new ArrayList<String>();
5354
String prefix = UUID.randomUUID().toString();
@@ -80,6 +81,57 @@ public void testListContainersTest() throws StorageException, URISyntaxException
8081

8182
assertEquals(0, containerList.size());
8283
}
84+
85+
/**
86+
* Try to list the containers to ensure maxResults validation is working.
87+
*
88+
* @throws StorageException
89+
* @throws URISyntaxException
90+
*/
91+
@Test
92+
@Category({ DevFabricTests.class, DevStoreTests.class, CloudTests.class })
93+
public void testListContainersMaxResultsValidation()
94+
throws StorageException, URISyntaxException {
95+
CloudBlobClient bClient = BlobTestHelper.createCloudBlobClient();
96+
String prefix = UUID.randomUUID().toString();
97+
98+
// Validation should cause each of these to fail.
99+
for(int i = 0; i >= -2; i--) {
100+
try {
101+
bClient.listContainersSegmented(
102+
prefix, ContainerListingDetails.ALL, i, null, null, null);
103+
fail();
104+
}
105+
catch (IllegalArgumentException e) {
106+
assertTrue(String.format(SR.PARAMETER_SHOULD_BE_GREATER_OR_EQUAL, "maxResults", 1)
107+
.equals(e.getMessage()));
108+
}
109+
}
110+
assertNotNull(bClient.listContainersSegmented("thereshouldntbeanycontainersswiththisprefix"));
111+
}
112+
113+
/**
114+
* Fetch result segments and ensure pageSize is null when unspecified and will cap at 5000.
115+
*
116+
* @throws StorageException
117+
* @throws URISyntaxException
118+
*/
119+
@Test
120+
@Category({ DevFabricTests.class, DevStoreTests.class, CloudTests.class })
121+
public void testListContainersResultSegment()
122+
throws StorageException, URISyntaxException {
123+
CloudBlobClient bClient = BlobTestHelper.createCloudBlobClient();
124+
125+
ResultSegment<CloudBlobContainer> segment1 = bClient.listContainersSegmented();
126+
assertNotNull(segment1);
127+
assertNull(segment1.getPageSize());
128+
129+
ResultSegment<CloudBlobContainer> segment2 = bClient.listContainersSegmented(null,
130+
ContainerListingDetails.ALL, 9001, null, null, null);
131+
assertNotNull(segment2);
132+
assertNotNull(segment2.getPageSize());
133+
assertEquals(5000, segment2.getPageSize().intValue());
134+
}
83135

84136
@Test
85137
@Category({ CloudTests.class })

microsoft-azure-storage-test/src/com/microsoft/azure/storage/blob/CloudBlobContainerTests.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ public void testCloudBlobContainerReference() throws StorageException, URISyntax
119119
CloudBlockBlob blockBlob = container.getBlockBlobReference("directory1/blob1");
120120
CloudPageBlob pageBlob = container.getPageBlobReference("directory2/blob2");
121121
CloudBlobDirectory directory = container.getDirectoryReference("directory3");
122-
CloudBlobDirectory directory2 = directory.getSubDirectoryReference("directory4");
122+
CloudBlobDirectory directory2 = directory.getDirectoryReference("directory4");
123123

124124
assertEquals(container.getStorageUri().toString(), blockBlob.getContainer().getStorageUri().toString());
125125
assertEquals(container.getStorageUri().toString(), pageBlob.getContainer().getStorageUri().toString());
@@ -463,6 +463,34 @@ public void testCloudBlobContainerListBlobs() throws StorageException, IOExcepti
463463

464464
assertTrue(blobNames.size() == 0);
465465
}
466+
467+
/**
468+
* Try to list the blobs in a container to ensure maxResults validation is working.
469+
*
470+
* @throws URISyntaxException
471+
* @throws StorageException
472+
* @throws IOException
473+
*/
474+
@Test
475+
@Category({ DevFabricTests.class, DevStoreTests.class })
476+
public void testCloudBlobContainerListBlobsMaxResultsValidation()
477+
throws StorageException, IOException, URISyntaxException {
478+
this.container.create();
479+
480+
// Validation should cause each of these to fail.
481+
for (int i = 0; i >= -2; i--) {
482+
try {
483+
this.container.listBlobsSegmented(
484+
"bb", false, EnumSet.noneOf(BlobListingDetails.class), i, null, null, null);
485+
fail();
486+
}
487+
catch (IllegalArgumentException e) {
488+
assertTrue(String.format(SR.PARAMETER_SHOULD_BE_GREATER_OR_EQUAL, "maxResults", 1)
489+
.equals(e.getMessage()));
490+
}
491+
}
492+
assertNotNull(this.container.listBlobsSegmented("thereshouldntbeanyblobswiththisprefix"));
493+
}
466494

467495
/**
468496
* List the blobs in a container

0 commit comments

Comments
 (0)