Skip to content

Commit

Permalink
Parse out of order ListBuckets response elements
Browse files Browse the repository at this point in the history
Currently, jclouds assumes that the ListBuckets response follows a
specific order: the <Owner> tag, followed by the <Buckets> tag. Within
the <Owner> tag, jclouds further assumes that the <ID> must occur before
the <DisplayName> 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
<DisplayName> tag before the <ID> tag. The patch changes the parser to
not depend on the order of the tags.
  • Loading branch information
timuralp authored and gaul committed Apr 4, 2021
1 parent c995a04 commit 04feb8f
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
* <p/>
*/
public class CanonicalUser {
private final String id;
private String id;
private String displayName;

public CanonicalUser() {}

public CanonicalUser(String id) {
this.id = id;
}
Expand All @@ -44,6 +46,8 @@ public String getId() {
return id;
}

public void setId(String id) { this.id = id; }

/**
* read-only as is maintained by Amazon.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult<Set<Buck

private Set<BucketMetadata> buckets = Sets.newLinkedHashSet();
private CanonicalUser currentOwner;
private String currentDisplayName;
private StringBuilder currentText = new StringBuilder();

private final DateService dateParser;
Expand All @@ -48,6 +49,7 @@ public class ListAllMyBucketsHandler extends ParseSax.HandlerWithResult<Set<Buck
@Inject
public ListAllMyBucketsHandler(DateService dateParser) {
this.dateParser = dateParser;
this.currentOwner = new CanonicalUser();
}

public Set<BucketMetadata> getResult() {
Expand All @@ -56,7 +58,7 @@ public Set<BucketMetadata> 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")) {
Expand Down
32 changes: 32 additions & 0 deletions apis/s3/src/test/java/org/jclouds/s3/xml/S3ParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ protected void tearDownInjector() {
}

public static final String listAllMyBucketsResultOn200 = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket><Bucket><Name>adrianjbosstest2</Name><CreationDate>2009-03-12T02:00:09.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>";
public static final String listAllMyBucketsResultOn200DisplayNameFirst = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Owner><DisplayName>TestName</DisplayName><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket></Buckets></ListAllMyBucketsResult>";
public static final String listAllMyBucketsResultOn200OwnerLast = "<ListAllMyBucketsResult xmlns=\"http://s3.amazonaws.com/doc/callables/\"><Buckets><Bucket><Name>adrianjbosstest</Name><CreationDate>2009-03-12T02:00:07.000Z</CreationDate></Bucket></Buckets><Owner><DisplayName>TestName</DisplayName><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID></Owner></ListAllMyBucketsResult>";

@Test
void testParseListAllMyBucketsSerialResponseTime() throws HttpException {
Expand Down Expand Up @@ -114,6 +116,36 @@ public void testCanParseListAllMyBuckets() throws HttpException {
assert container2.getOwner().equals(owner);
}

@Test
public void testCanParseListAllMyBucketsDisplayNameFirst() throws HttpException {
Set<BucketMetadata> 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<BucketMetadata> 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 = "<ListContainerHandler xmlns=\"http://s3.amazonaws.com/doc/2006-03-01/\"><Name>adrianjbosstest</Name><Prefix></Prefix><Marker></Marker><MaxKeys>1000</MaxKeys><IsTruncated>false</IsTruncated><Contents><Key>3366</Key><LastModified>2009-03-12T02:00:13.000Z</LastModified><ETag>&quot;9d7bb64e8e18ee34eec06dd2cf37b766&quot;</ETag><Size>136</Size><Owner><ID>e1a5f66a480ca99a4fdfe8e318c3020446c9989d7004e7778029fbcc5d990fa0</ID><DisplayName>ferncam</DisplayName></Owner><StorageClass>STANDARD</StorageClass></Contents></ListContainerHandler>";

public void testCanParseListContainerResult() throws HttpException {
Expand Down

0 comments on commit 04feb8f

Please sign in to comment.