From 04feb8f8482e48b6c26166edb3d6fd5a607d858b Mon Sep 17 00:00:00 2001 From: Timur Alperovich Date: Sat, 3 Apr 2021 18:06:41 -0700 Subject: [PATCH] Parse out of order ListBuckets response elements Currently, jclouds assumes that the ListBuckets response follows a specific order: the tag, followed by the tag. Within the tag, jclouds further assumes that the must occur before the tag. If the XML body does not adhere to this order, the parser throws a NullPointerException. DigitalOcean spaces does not adhere to this order and returns the tag before the tag. The patch changes the parser to not depend on the order of the tags. --- .../org/jclouds/s3/domain/CanonicalUser.java | 6 +++- .../s3/xml/ListAllMyBucketsHandler.java | 4 ++- .../java/org/jclouds/s3/xml/S3ParserTest.java | 32 +++++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/apis/s3/src/main/java/org/jclouds/s3/domain/CanonicalUser.java b/apis/s3/src/main/java/org/jclouds/s3/domain/CanonicalUser.java index f4fbc55c812..8880b533a9e 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/domain/CanonicalUser.java +++ b/apis/s3/src/main/java/org/jclouds/s3/domain/CanonicalUser.java @@ -23,9 +23,11 @@ *

*/ public class CanonicalUser { - private final String id; + private String id; private String displayName; + public CanonicalUser() {} + public CanonicalUser(String id) { this.id = id; } @@ -44,6 +46,8 @@ public String getId() { return id; } + public void setId(String id) { this.id = id; } + /** * read-only as is maintained by Amazon. */ diff --git a/apis/s3/src/main/java/org/jclouds/s3/xml/ListAllMyBucketsHandler.java b/apis/s3/src/main/java/org/jclouds/s3/xml/ListAllMyBucketsHandler.java index 39ada833a3a..058a358e840 100644 --- a/apis/s3/src/main/java/org/jclouds/s3/xml/ListAllMyBucketsHandler.java +++ b/apis/s3/src/main/java/org/jclouds/s3/xml/ListAllMyBucketsHandler.java @@ -39,6 +39,7 @@ public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult buckets = Sets.newLinkedHashSet(); private CanonicalUser currentOwner; + private String currentDisplayName; private StringBuilder currentText = new StringBuilder(); private final DateService dateParser; @@ -48,6 +49,7 @@ public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult getResult() { @@ -56,7 +58,7 @@ public Set getResult() { public void endElement(String uri, String name, String qName) { if (qName.equals("ID")) { // owner stuff - currentOwner = new CanonicalUser(currentOrNull(currentText)); + currentOwner.setId(currentOrNull(currentText)); } else if (qName.equals("DisplayName")) { currentOwner.setDisplayName(currentOrNull(currentText)); } else if (qName.equals("Bucket")) { diff --git a/apis/s3/src/test/java/org/jclouds/s3/xml/S3ParserTest.java b/apis/s3/src/test/java/org/jclouds/s3/xml/S3ParserTest.java index b5d2bd93978..6cd1485ced4 100644 --- a/apis/s3/src/test/java/org/jclouds/s3/xml/S3ParserTest.java +++ b/apis/s3/src/test/java/org/jclouds/s3/xml/S3ParserTest.java @@ -70,6 +70,8 @@ protected void tearDownInjector() { } public static final String listAllMyBucketsResultOn200 = "e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0adrianjbosstest2009-03-12T02:00:07.000Zadrianjbosstest22009-03-12T02:00:09.000Z"; + public static final String listAllMyBucketsResultOn200DisplayNameFirst = "TestNamee1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0adrianjbosstest2009-03-12T02:00:07.000Z"; + public static final String listAllMyBucketsResultOn200OwnerLast = "adrianjbosstest2009-03-12T02:00:07.000ZTestNamee1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0"; @Test void testParseListAllMyBucketsSerialResponseTime() throws HttpException { @@ -114,6 +116,36 @@ public void testCanParseListAllMyBuckets() throws HttpException { assert container2.getOwner().equals(owner); } + @Test + public void testCanParseListAllMyBucketsDisplayNameFirst() throws HttpException { + Set s3Buckets = factory.create(injector.getInstance(ListAllMyBucketsHandler.class)).parse( + Strings2.toInputStream(listAllMyBucketsResultOn200DisplayNameFirst)); + BucketMetadata container = Iterables.get(s3Buckets, 0); + assert container.getName().equals("adrianjbosstest"); + Date expectedDate1 = new SimpleDateFormatDateService().iso8601DateParse("2009-03-12T02:00:07.000Z"); + Date date = container.getCreationDate(); + assert date.equals(expectedDate1); + assert s3Buckets.size() == 1; + CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0", + "TestName"); + assert container.getOwner().equals(owner); + } + + @Test + public void testCanParseListAllMyBucketsOwnerLast() throws HttpException { + Set s3Buckets = factory.create(injector.getInstance(ListAllMyBucketsHandler.class)).parse( + Strings2.toInputStream(listAllMyBucketsResultOn200OwnerLast)); + BucketMetadata container = Iterables.get(s3Buckets, 0); + assert container.getName().equals("adrianjbosstest"); + Date expectedDate = new SimpleDateFormatDateService().iso8601DateParse("2009-03-12T02:00:07.000Z"); + Date date1 = container.getCreationDate(); + assert date1.equals(expectedDate); + assert s3Buckets.size() == 1; + CanonicalUser owner = new CanonicalUser("e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0", + "TestName"); + assert container.getOwner().equals(owner); + } + public static final String listContainerResult = "adrianjbosstest1000false33662009-03-12T02:00:13.000Z"9d7bb64e8e18ee34eec06dd2cf37b766"136e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0ferncamSTANDARD"; public void testCanParseListContainerResult() throws HttpException {