You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ozone.apache.org by ad...@apache.org on 2023/02/20 15:34:07 UTC

[ozone] branch master updated: HDDS-7710. Support AWS s3 ListObjects API's encodingType request parameter (#4127)

This is an automated email from the ASF dual-hosted git repository.

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 204f3b4b97 HDDS-7710. Support AWS s3 ListObjects API's encodingType request parameter (#4127)
204f3b4b97 is described below

commit 204f3b4b9760ae12000d04aa63bc068cec6903c9
Author: XiChen <32...@users.noreply.github.com>
AuthorDate: Mon Feb 20 23:34:01 2023 +0800

    HDDS-7710. Support AWS s3 ListObjects API's encodingType request parameter (#4127)
---
 .../hadoop/ozone/s3/commontypes/CommonPrefix.java  |   8 +-
 .../{CommonPrefix.java => EncodingTypeObject.java} |  40 ++++---
 .../hadoop/ozone/s3/commontypes/KeyMetadata.java   |   6 +-
 .../ozone/s3/commontypes/ObjectKeyNameAdapter.java |  14 ++-
 .../hadoop/ozone/s3/endpoint/BucketEndpoint.java   |  32 +++++-
 .../ozone/s3/endpoint/ListObjectResponse.java      |  33 ++++--
 .../s3/commontypes/TestObjectKeyNameAdapter.java   |  23 ++--
 .../hadoop/ozone/s3/endpoint/TestBucketList.java   | 121 +++++++++++++++++++--
 8 files changed, 216 insertions(+), 61 deletions(-)

diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/CommonPrefix.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/CommonPrefix.java
index 7815d5182c..54d250b46b 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/CommonPrefix.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/CommonPrefix.java
@@ -30,20 +30,20 @@ public class CommonPrefix {
 
   @XmlJavaTypeAdapter(ObjectKeyNameAdapter.class)
   @XmlElement(name = "Prefix")
-  private String prefix;
+  private EncodingTypeObject prefix;
 
-  public CommonPrefix(String prefix) {
+  public CommonPrefix(EncodingTypeObject prefix) {
     this.prefix = prefix;
   }
 
   public CommonPrefix() {
   }
 
-  public String getPrefix() {
+  public EncodingTypeObject getPrefix() {
     return prefix;
   }
 
-  public void setPrefix(String prefix) {
+  public void setPrefix(EncodingTypeObject prefix) {
     this.prefix = prefix;
   }
 }
diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/CommonPrefix.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/EncodingTypeObject.java
similarity index 51%
copy from hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/CommonPrefix.java
copy to hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/EncodingTypeObject.java
index 7815d5182c..02540ff57c 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/CommonPrefix.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/EncodingTypeObject.java
@@ -17,33 +17,37 @@
  */
 package org.apache.hadoop.ozone.s3.commontypes;
 
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
+import javax.annotation.Nullable;
 
 /**
- * Directory name ("key prefix") in case of listing.
+ * A converter to encode string if needed.
  */
-@XmlAccessorType(XmlAccessType.FIELD)
-public class CommonPrefix {
+public final class EncodingTypeObject {
+  private final String encodingType;
+  private final String name;
 
-  @XmlJavaTypeAdapter(ObjectKeyNameAdapter.class)
-  @XmlElement(name = "Prefix")
-  private String prefix;
-
-  public CommonPrefix(String prefix) {
-    this.prefix = prefix;
+  private EncodingTypeObject(String name, @Nullable String encodingType) {
+    this.encodingType = encodingType;
+    this.name = name;
   }
 
-  public CommonPrefix() {
+  @Nullable public String getEncodingType() {
+    return encodingType;
   }
 
-  public String getPrefix() {
-    return prefix;
+  public String getName() {
+    return name;
   }
 
-  public void setPrefix(String prefix) {
-    this.prefix = prefix;
+  /**
+   * Create a EncodingTypeObject Object, if the parameter name is null.
+   * @return If name is null return null else return a EncodingTypeObject object
+   */
+  @Nullable public static EncodingTypeObject createNullable(
+      @Nullable String name, @Nullable String encodingType) {
+    if (name == null) {
+      return null;
+    }
+    return new EncodingTypeObject(name, encodingType);
   }
 }
diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/KeyMetadata.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/KeyMetadata.java
index 63ab0d2b05..47b59cfcc0 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/KeyMetadata.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/KeyMetadata.java
@@ -31,7 +31,7 @@ public class KeyMetadata {
 
   @XmlJavaTypeAdapter(ObjectKeyNameAdapter.class)
   @XmlElement(name = "Key")
-  private String key; // or the Object Name
+  private EncodingTypeObject key; // or the Object Name
 
   @XmlJavaTypeAdapter(IsoDateAdapter.class)
   @XmlElement(name = "LastModified")
@@ -46,11 +46,11 @@ public class KeyMetadata {
   @XmlElement(name = "StorageClass")
   private String storageClass;
 
-  public String getKey() {
+  public EncodingTypeObject getKey() {
     return key;
   }
 
-  public void setKey(String key) {
+  public void setKey(EncodingTypeObject key) {
     this.key = key;
   }
 
diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/ObjectKeyNameAdapter.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/ObjectKeyNameAdapter.java
index 15695c42b1..fa62607967 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/ObjectKeyNameAdapter.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/commontypes/ObjectKeyNameAdapter.java
@@ -27,16 +27,20 @@ import java.io.UnsupportedEncodingException;
  * A converter to convert raw-String to S3 compliant object key name.
  * ref: https://docs.aws.amazon.com/AmazonS3/latest/userguide/object-keys.html
  */
-public class ObjectKeyNameAdapter extends XmlAdapter<String, String> {
+public class ObjectKeyNameAdapter extends
+    XmlAdapter<String, EncodingTypeObject> {
   @Override
-  public String unmarshal(String s) {
+  public EncodingTypeObject unmarshal(String s) {
     throw new UnsupportedOperationException();
   }
 
   @Override
-  public String marshal(String s)
+  public String marshal(EncodingTypeObject s)
       throws UnsupportedEncodingException {
-    return S3Utils.urlEncode(s)
-        .replaceAll("%2F", "/");
+    if (s.getEncodingType() != null && s.getEncodingType().equals("url")) {
+      return S3Utils.urlEncode(s.getName())
+          .replaceAll("%2F", "/");
+    }
+    return s.getName();
   }
 }
diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java
index 18272c2f10..bb1fb95275 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/BucketEndpoint.java
@@ -29,6 +29,7 @@ import org.apache.hadoop.ozone.client.OzoneVolume;
 import org.apache.hadoop.ozone.om.exceptions.OMException;
 import org.apache.hadoop.ozone.om.exceptions.OMException.ResultCodes;
 import org.apache.hadoop.ozone.om.helpers.OzoneAclUtil;
+import org.apache.hadoop.ozone.s3.commontypes.EncodingTypeObject;
 import org.apache.hadoop.ozone.s3.commontypes.KeyMetadata;
 import org.apache.hadoop.ozone.s3.endpoint.MultiDeleteRequest.DeleteObject;
 import org.apache.hadoop.ozone.s3.endpoint.MultiDeleteResponse.DeletedObject;
@@ -158,15 +159,31 @@ public class BucketEndpoint extends EndpointBase {
       throw ex;
     }
 
+    // The valid encodingType Values is "url"
+    if (encodingType != null && !encodingType.equals(ENCODING_TYPE)) {
+      throw S3ErrorTable.newError(S3ErrorTable.INVALID_ARGUMENT, encodingType);
+    }
+
+    // If you specify the encoding-type request parameter,should return
+    // encoded key name values in the following response elements:
+    //   Delimiter, Prefix, Key, and StartAfter.
+    //
+    // For detail refer:
+    // https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html
+    // #AmazonS3-ListObjectsV2-response-EncodingType
+    //
     ListObjectResponse response = new ListObjectResponse();
-    response.setDelimiter(delimiter);
+    response.setDelimiter(
+        EncodingTypeObject.createNullable(delimiter, encodingType));
     response.setName(bucketName);
-    response.setPrefix(prefix);
+    response.setPrefix(EncodingTypeObject.createNullable(prefix, encodingType));
     response.setMarker(marker == null ? "" : marker);
     response.setMaxKeys(maxKeys);
-    response.setEncodingType(ENCODING_TYPE);
+    response.setEncodingType(encodingType);
     response.setTruncated(false);
     response.setContinueToken(continueToken);
+    response.setStartAfter(
+        EncodingTypeObject.createNullable(startAfter, encodingType));
 
     String prevDir = null;
     if (continueToken != null) {
@@ -186,14 +203,16 @@ public class BucketEndpoint extends EndpointBase {
           String dirName = relativeKeyName.substring(0, relativeKeyName
               .indexOf(delimiter));
           if (!dirName.equals(prevDir)) {
-            response.addPrefix(prefix + dirName + delimiter);
+            response.addPrefix(EncodingTypeObject.createNullable(
+                prefix + dirName + delimiter, encodingType));
             prevDir = dirName;
             count++;
           }
         } else if (relativeKeyName.endsWith(delimiter)) {
           // means or key is same as prefix with delimiter at end and ends with
           // delimiter. ex: dir/, where prefix is dir and delimiter is /
-          response.addPrefix(relativeKeyName);
+          response.addPrefix(
+              EncodingTypeObject.createNullable(relativeKeyName, encodingType));
           count++;
         } else {
           // means our key is matched with prefix if prefix is given and it
@@ -648,7 +667,8 @@ public class BucketEndpoint extends EndpointBase {
 
   private void addKey(ListObjectResponse response, OzoneKey next) {
     KeyMetadata keyMetadata = new KeyMetadata();
-    keyMetadata.setKey(next.getName());
+    keyMetadata.setKey(EncodingTypeObject.createNullable(next.getName(),
+        response.getEncodingType()));
     keyMetadata.setSize(next.getDataSize());
     keyMetadata.setETag("" + next.getModificationTime());
     if (next.getReplicationType().toString().equals(ReplicationType
diff --git a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ListObjectResponse.java b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ListObjectResponse.java
index fb707b174d..bfd9b7cb77 100644
--- a/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ListObjectResponse.java
+++ b/hadoop-ozone/s3gateway/src/main/java/org/apache/hadoop/ozone/s3/endpoint/ListObjectResponse.java
@@ -22,11 +22,14 @@ import javax.xml.bind.annotation.XmlAccessType;
 import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
+import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
 import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.hadoop.ozone.s3.commontypes.CommonPrefix;
+import org.apache.hadoop.ozone.s3.commontypes.EncodingTypeObject;
 import org.apache.hadoop.ozone.s3.commontypes.KeyMetadata;
+import org.apache.hadoop.ozone.s3.commontypes.ObjectKeyNameAdapter;
 
 /**
  * Response from the ListObject RPC Call.
@@ -40,7 +43,8 @@ public class ListObjectResponse {
   private String name;
 
   @XmlElement(name = "Prefix")
-  private String prefix;
+  @XmlJavaTypeAdapter(ObjectKeyNameAdapter.class)
+  private EncodingTypeObject prefix;
 
   @XmlElement(name = "Marker")
   private String marker;
@@ -51,11 +55,12 @@ public class ListObjectResponse {
   @XmlElement(name = "KeyCount")
   private int keyCount;
 
+  @XmlJavaTypeAdapter(ObjectKeyNameAdapter.class)
   @XmlElement(name = "Delimiter")
-  private String delimiter = "/";
+  private EncodingTypeObject delimiter;
 
   @XmlElement(name = "EncodingType")
-  private String encodingType = "url";
+  private String encodingType;
 
   @XmlElement(name = "IsTruncated")
   private boolean isTruncated;
@@ -75,6 +80,10 @@ public class ListObjectResponse {
   @XmlElement(name = "CommonPrefixes")
   private List<CommonPrefix> commonPrefixes = new ArrayList<>();
 
+  @XmlJavaTypeAdapter(ObjectKeyNameAdapter.class)
+  @XmlElement(name = "StartAfter")
+  private EncodingTypeObject startAfter;
+
   public String getName() {
     return name;
   }
@@ -83,11 +92,11 @@ public class ListObjectResponse {
     this.name = name;
   }
 
-  public String getPrefix() {
+  public EncodingTypeObject getPrefix() {
     return prefix;
   }
 
-  public void setPrefix(String prefix) {
+  public void setPrefix(EncodingTypeObject prefix) {
     this.prefix = prefix;
   }
 
@@ -107,11 +116,11 @@ public class ListObjectResponse {
     this.maxKeys = maxKeys;
   }
 
-  public String getDelimiter() {
+  public EncodingTypeObject getDelimiter() {
     return delimiter;
   }
 
-  public void setDelimiter(String delimiter) {
+  public void setDelimiter(EncodingTypeObject delimiter) {
     this.delimiter = delimiter;
   }
 
@@ -153,7 +162,7 @@ public class ListObjectResponse {
     contents.add(keyMetadata);
   }
 
-  public void addPrefix(String relativeKeyName) {
+  public void addPrefix(EncodingTypeObject relativeKeyName) {
     commonPrefixes.add(new CommonPrefix(relativeKeyName));
   }
 
@@ -188,4 +197,12 @@ public class ListObjectResponse {
   public String getNextMarker() {
     return nextMarker;
   }
+
+  public void setStartAfter(EncodingTypeObject startAfter) {
+    this.startAfter = startAfter;
+  }
+
+  public EncodingTypeObject getStartAfter() {
+    return startAfter;
+  }
 }
diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/commontypes/TestObjectKeyNameAdapter.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/commontypes/TestObjectKeyNameAdapter.java
index df4b5f43d9..5a24a69f07 100644
--- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/commontypes/TestObjectKeyNameAdapter.java
+++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/commontypes/TestObjectKeyNameAdapter.java
@@ -19,6 +19,8 @@
  */
 package org.apache.hadoop.ozone.s3.commontypes;
 
+import static org.apache.hadoop.ozone.s3.util.S3Consts.ENCODING_TYPE;
+
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -29,15 +31,22 @@ import javax.xml.bind.annotation.adapters.XmlAdapter;
 public class TestObjectKeyNameAdapter {
   @Test
   public void testEncodeResult() throws Exception {
-    Assert.assertEquals("abc/",
-        getAdapter().marshal("abc/"));
-    Assert.assertEquals("a+b+c/",
-        getAdapter().marshal("a b c/"));
-    Assert.assertEquals("a%2Bb%2Bc/",
-        getAdapter().marshal("a+b+c/"));
+    Assert.assertEquals("abc/", getAdapter()
+        .marshal(EncodingTypeObject.createNullable("abc/", ENCODING_TYPE)));
+    Assert.assertEquals("a+b+c/", getAdapter()
+        .marshal(EncodingTypeObject.createNullable("a b c/", ENCODING_TYPE)));
+    Assert.assertEquals("a%2Bb%2Bc/", getAdapter()
+        .marshal(EncodingTypeObject.createNullable("a+b+c/", ENCODING_TYPE)));
+
+    Assert.assertEquals("abc/", getAdapter()
+        .marshal(EncodingTypeObject.createNullable("abc/", null)));
+    Assert.assertEquals("a b c/", getAdapter()
+        .marshal(EncodingTypeObject.createNullable("a b c/", null)));
+    Assert.assertEquals("a+b+c/", getAdapter()
+        .marshal(EncodingTypeObject.createNullable("a+b+c/", null)));
   }
 
-  private XmlAdapter<String, String> getAdapter() {
+  private XmlAdapter<String, EncodingTypeObject> getAdapter() {
     return (new ObjectKeyNameAdapter());
   }
 }
diff --git a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketList.java b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketList.java
index 3cacc116cf..a597233f2e 100644
--- a/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketList.java
+++ b/hadoop-ozone/s3gateway/src/test/java/org/apache/hadoop/ozone/s3/endpoint/TestBucketList.java
@@ -24,9 +24,13 @@ import java.io.IOException;
 import org.apache.hadoop.ozone.client.OzoneBucket;
 import org.apache.hadoop.ozone.client.OzoneClient;
 import org.apache.hadoop.ozone.client.OzoneClientStub;
+import org.apache.hadoop.ozone.s3.commontypes.EncodingTypeObject;
 import org.apache.hadoop.ozone.s3.exception.OS3Exception;
 
+import org.apache.hadoop.ozone.s3.exception.S3ErrorTable;
 import org.junit.Assert;
+
+import static org.apache.hadoop.ozone.s3.util.S3Consts.ENCODING_TYPE;
 import static org.junit.Assert.fail;
 import org.junit.Test;
 
@@ -51,11 +55,11 @@ public class TestBucketList {
 
     Assert.assertEquals(1, getBucketResponse.getCommonPrefixes().size());
     Assert.assertEquals("dir1/",
-        getBucketResponse.getCommonPrefixes().get(0).getPrefix());
+        getBucketResponse.getCommonPrefixes().get(0).getPrefix().getName());
 
     Assert.assertEquals(1, getBucketResponse.getContents().size());
     Assert.assertEquals("file1",
-        getBucketResponse.getContents().get(0).getKey());
+        getBucketResponse.getContents().get(0).getKey().getName());
 
   }
 
@@ -74,7 +78,7 @@ public class TestBucketList {
 
     Assert.assertEquals(1, getBucketResponse.getCommonPrefixes().size());
     Assert.assertEquals("dir1/",
-        getBucketResponse.getCommonPrefixes().get(0).getPrefix());
+        getBucketResponse.getCommonPrefixes().get(0).getPrefix().getName());
 
     Assert.assertEquals(0, getBucketResponse.getContents().size());
 
@@ -99,11 +103,11 @@ public class TestBucketList {
 
     Assert.assertEquals(1, getBucketResponse.getCommonPrefixes().size());
     Assert.assertEquals("dir1/dir2/",
-        getBucketResponse.getCommonPrefixes().get(0).getPrefix());
+        getBucketResponse.getCommonPrefixes().get(0).getPrefix().getName());
 
     Assert.assertEquals(1, getBucketResponse.getContents().size());
     Assert.assertEquals("dir1/file2",
-        getBucketResponse.getContents().get(0).getKey());
+        getBucketResponse.getContents().get(0).getKey().getName());
 
   }
 
@@ -144,7 +148,7 @@ public class TestBucketList {
 
     Assert.assertEquals(3, getBucketResponse.getCommonPrefixes().size());
     Assert.assertEquals("file2", getBucketResponse.getContents().get(0)
-        .getKey());
+        .getKey().getName());
 
   }
 
@@ -240,9 +244,9 @@ public class TestBucketList {
     Assert.assertEquals(0, getBucketResponse.getContents().size());
     Assert.assertEquals(2, getBucketResponse.getCommonPrefixes().size());
     Assert.assertEquals("test/dir1/",
-        getBucketResponse.getCommonPrefixes().get(0).getPrefix());
+        getBucketResponse.getCommonPrefixes().get(0).getPrefix().getName());
     Assert.assertEquals("test/dir2/",
-        getBucketResponse.getCommonPrefixes().get(1).getPrefix());
+        getBucketResponse.getCommonPrefixes().get(1).getPrefix().getName());
 
     getBucketResponse =
         (ListObjectResponse) getBucket.get("b1", "/", null, null, maxKeys,
@@ -251,9 +255,9 @@ public class TestBucketList {
     Assert.assertEquals(1, getBucketResponse.getContents().size());
     Assert.assertEquals(1, getBucketResponse.getCommonPrefixes().size());
     Assert.assertEquals("test/dir3/",
-        getBucketResponse.getCommonPrefixes().get(0).getPrefix());
+        getBucketResponse.getCommonPrefixes().get(0).getPrefix().getName());
     Assert.assertEquals("test/file8",
-        getBucketResponse.getContents().get(0).getKey());
+        getBucketResponse.getContents().get(0).getKey().getName());
 
   }
 
@@ -363,6 +367,103 @@ public class TestBucketList {
 
   }
 
+  @Test
+  public void testEncodingType() throws IOException, OS3Exception {
+    /*
+    * OP1 -> Create key "data=1970" and "data==1970" in a bucket
+    * OP2 -> List Object, if encodingType == url the result will be like blow:
+
+        <?xml version="1.0" encoding="UTF-8"?>
+          <ListBucketResult xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
+              ...
+              <Prefix>data%3D</Prefix>
+              <StartAfter>data%3D</StartAfter>
+              <Delimiter>%3D</Delimiter>
+              <EncodingType>url</EncodingType>
+              ...
+              <Contents>
+                  <Key>data%3D1970</Key>
+                  ....
+              </Contents>
+              <CommonPrefixes>
+                  <Prefix>data%3D%3D</Prefix>
+              </CommonPrefixes>
+          </ListBucketResult>
+
+      if encodingType == null , the = will not be encoded to "%3D"
+    * */
+
+    BucketEndpoint getBucket = new BucketEndpoint();
+    OzoneClient ozoneClient =
+        createClientWithKeys("data=1970", "data==1970");
+    getBucket.setClient(ozoneClient);
+
+    String delimiter = "=";
+    String prefix = "data=";
+    String startAfter = "data=";
+    String encodingType = ENCODING_TYPE;
+
+    ListObjectResponse response = (ListObjectResponse) getBucket.get(
+        "b1", delimiter, encodingType, null, 1000, prefix,
+        null, startAfter, null, null, null).getEntity();
+
+    // Assert encodingType == url.
+    // The Object name will be encoded by ObjectKeyNameAdapter
+    // if encodingType == url
+    assertEncodingTypeObject(delimiter, encodingType, response.getDelimiter());
+    assertEncodingTypeObject(prefix, encodingType, response.getPrefix());
+    assertEncodingTypeObject(startAfter, encodingType,
+        response.getStartAfter());
+    Assert.assertNotNull(response.getCommonPrefixes());
+    Assert.assertNotNull(response.getContents());
+    assertEncodingTypeObject(prefix + delimiter, encodingType,
+        response.getCommonPrefixes().get(0).getPrefix());
+    Assert.assertEquals(encodingType,
+        response.getContents().get(0).getKey().getEncodingType());
+
+    response = (ListObjectResponse) getBucket.get(
+        "b1", delimiter, null, null, 1000, prefix,
+        null, startAfter, null, null, null).getEntity();
+
+    // Assert encodingType == null.
+    // The Object name will not be encoded by ObjectKeyNameAdapter
+    // if encodingType == null
+    assertEncodingTypeObject(delimiter, null, response.getDelimiter());
+    assertEncodingTypeObject(prefix, null, response.getPrefix());
+    assertEncodingTypeObject(startAfter, null, response.getStartAfter());
+    Assert.assertNotNull(response.getCommonPrefixes());
+    Assert.assertNotNull(response.getContents());
+    assertEncodingTypeObject(prefix + delimiter, null,
+        response.getCommonPrefixes().get(0).getPrefix());
+    Assert.assertNull(response.getContents().get(0).getKey().getEncodingType());
+
+  }
+
+  @Test
+  public void testEncodingTypeException() throws IOException, OS3Exception {
+    BucketEndpoint getBucket = new BucketEndpoint();
+    OzoneClient client = new OzoneClientStub();
+    client.getObjectStore().createS3Bucket("b1");
+    getBucket.setClient(client);
+    try {
+      ListObjectResponse response = (ListObjectResponse) getBucket.get(
+          "b1", null, "unSupportType", null, 1000, null,
+          null, null, null, null, null).getEntity();
+      Assert.fail();
+    } catch (Exception e) {
+      Assert.assertTrue(e instanceof OS3Exception);
+      Assert.assertEquals(S3ErrorTable.INVALID_ARGUMENT.getCode(),
+          ((OS3Exception) e).getCode());
+    }
+
+  }
+
+  private void assertEncodingTypeObject(
+      String exceptName, String exceptEncodingType, EncodingTypeObject object) {
+    Assert.assertEquals(exceptName, object.getName());
+    Assert.assertEquals(exceptEncodingType, object.getEncodingType());
+  }
+
   private OzoneClient createClientWithKeys(String... keys) throws IOException {
     OzoneClient client = new OzoneClientStub();
 


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@ozone.apache.org
For additional commands, e-mail: commits-help@ozone.apache.org