You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by cn...@apache.org on 2016/03/09 19:20:34 UTC

[1/2] hadoop git commit: HDFS-9916. OzoneHandler : Add Key handler. Contributed by Anu Engineer.

Repository: hadoop
Updated Branches:
  refs/heads/HDFS-7240 1db15fb58 -> 28f770d8b


HDFS-9916. OzoneHandler : Add Key handler. Contributed by Anu Engineer.


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/ea0bb4a4
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/ea0bb4a4
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/ea0bb4a4

Branch: refs/heads/HDFS-7240
Commit: ea0bb4a41ef0a26abd8f3fabc6fa9000d77f2a8f
Parents: 1db15fb
Author: Chris Nauroth <cn...@apache.org>
Authored: Wed Mar 9 10:17:05 2016 -0800
Committer: Chris Nauroth <cn...@apache.org>
Committed: Wed Mar 9 10:17:05 2016 -0800

----------------------------------------------------------------------
 .../hadoop/ozone/web/exceptions/ErrorTable.java |   9 +-
 .../ozone/web/handlers/BucketHandler.java       |  22 ++--
 .../web/handlers/BucketProcessTemplate.java     |  15 ++-
 .../apache/hadoop/ozone/web/headers/Header.java |   1 +
 .../ozone/web/interfaces/StorageHandler.java    |  64 +++++++++++
 .../web/localstorage/LocalStorageHandler.java   | 115 +++++++++++++------
 .../web/storage/DistributedStorageHandler.java  |  72 +++++++++++-
 7 files changed, 245 insertions(+), 53 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/ea0bb4a4/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/exceptions/ErrorTable.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/exceptions/ErrorTable.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/exceptions/ErrorTable.java
index 25af983..b6a5084 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/exceptions/ErrorTable.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/exceptions/ErrorTable.java
@@ -202,9 +202,12 @@ public final class ErrorTable {
                                         Exception ex) {
     OzoneException err =
         new OzoneException(e.getHttpCode(), e.getShortMessage(), ex);
-    err.setRequestId(args.getRequestID());
-    err.setResource(args.getResourceName());
-    err.setHostID(args.getHostName());
+
+    if(args != null) {
+      err.setRequestId(args.getRequestID());
+      err.setResource(args.getResourceName());
+      err.setHostID(args.getHostName());
+    }
     err.setMessage(ex.getMessage());
     return err;
   }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ea0bb4a4/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketHandler.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketHandler.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketHandler.java
index 2005367..baa6142 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketHandler.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketHandler.java
@@ -174,18 +174,16 @@ public class BucketHandler implements Bucket {
       public Response doProcess(BucketArgs args)
           throws OzoneException, IOException {
         switch (info) {
-          //TODO : Enable when Object support is enabled.
-          //          case Header.OZONE_LIST_QUERY_KEY:
-          //            ListArgs listArgs = new ListArgs(args, prefix,
-          // maxKeys, startPage);
-          //            return getBucketKeysList(listArgs);
-          case Header.OZONE_LIST_QUERY_BUCKET:
-            return getBucketInfoResponse(args);
-          default:
-            OzoneException ozException =
-                ErrorTable.newError(ErrorTable.INVALID_QUERY_PARAM, args);
-            ozException.setMessage("Unrecognized query param : " + info);
-            throw ozException;
+        case Header.OZONE_LIST_QUERY_KEY:
+          ListArgs listArgs = new ListArgs(args, prefix, maxKeys, startPage);
+          return getBucketKeysList(listArgs);
+        case Header.OZONE_LIST_QUERY_BUCKET:
+          return getBucketInfoResponse(args);
+        default:
+          OzoneException ozException =
+              ErrorTable.newError(ErrorTable.INVALID_QUERY_PARAM, args);
+          ozException.setMessage("Unrecognized query param : " + info);
+          throw ozException;
         }
       }
     }.handleCall(volume, bucket, req, uriInfo, headers);

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ea0bb4a4/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketProcessTemplate.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketProcessTemplate.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketProcessTemplate.java
index a312939..7046b8f 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketProcessTemplate.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/BucketProcessTemplate.java
@@ -26,6 +26,7 @@ import org.apache.hadoop.ozone.web.headers.Header;
 import org.apache.hadoop.ozone.web.interfaces.StorageHandler;
 import org.apache.hadoop.ozone.web.interfaces.UserAuth;
 import org.apache.hadoop.ozone.web.response.BucketInfo;
+import org.apache.hadoop.ozone.web.response.ListKeys;
 import org.apache.hadoop.ozone.web.utils.OzoneConsts;
 import org.apache.hadoop.ozone.web.utils.OzoneUtils;
 
@@ -179,7 +180,6 @@ public abstract class BucketProcessTemplate {
    *
    * @return List of ACLs
    *
-   * @throws OzoneException
    */
   List<String> getAcls(BucketArgs args, String tag)  {
     List<String> aclStrings =
@@ -275,4 +275,17 @@ public abstract class BucketProcessTemplate {
     return OzoneUtils.getResponse(args, HTTP_OK, info.toJsonString());
   }
 
+  /**
+   * Returns list of objects in a bucket.
+   * @param args - ListArgs
+   * @return Response
+   * @throws IOException
+   * @throws OzoneException
+   */
+  Response getBucketKeysList(ListArgs args) throws IOException, OzoneException {
+    StorageHandler fs = StorageHandlerBuilder.getStorageHandler();
+    ListKeys objects = fs.listKeys(args);
+    return OzoneUtils.getResponse(args, HTTP_OK, objects.toJsonString());
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ea0bb4a4/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/headers/Header.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/headers/Header.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/headers/Header.java
index 45f36ae..0bba50b 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/headers/Header.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/headers/Header.java
@@ -56,6 +56,7 @@ public final class Header {
 
   public static final String OZONE_LIST_QUERY_TAG ="info";
   public static final String OZONE_QUOTA_QUERY_TAG ="quota";
+  public static final String CONTENT_MD5 = "Content-MD5";
 
 
 

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ea0bb4a4/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/StorageHandler.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/StorageHandler.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/StorageHandler.java
index 6759888..0657ccb 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/StorageHandler.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/StorageHandler.java
@@ -19,16 +19,21 @@
 package org.apache.hadoop.ozone.web.interfaces;
 
 import org.apache.hadoop.classification.InterfaceAudience;
+import org.apache.hadoop.hdfs.server.datanode.fsdataset.LengthInputStream;
 import org.apache.hadoop.ozone.web.exceptions.OzoneException;
 import org.apache.hadoop.ozone.web.handlers.BucketArgs;
+import org.apache.hadoop.ozone.web.handlers.KeyArgs;
+import org.apache.hadoop.ozone.web.handlers.ListArgs;
 import org.apache.hadoop.ozone.web.handlers.UserArgs;
 import org.apache.hadoop.ozone.web.handlers.VolumeArgs;
 import org.apache.hadoop.ozone.web.response.BucketInfo;
 import org.apache.hadoop.ozone.web.response.ListBuckets;
+import org.apache.hadoop.ozone.web.response.ListKeys;
 import org.apache.hadoop.ozone.web.response.ListVolumes;
 import org.apache.hadoop.ozone.web.response.VolumeInfo;
 
 import java.io.IOException;
+import java.io.OutputStream;
 
 /**
  * Storage handler Interface is the Interface between
@@ -205,5 +210,64 @@ public interface StorageHandler {
    */
   BucketInfo getBucketInfo(BucketArgs args) throws IOException, OzoneException;
 
+  /**
+   * Writes a key in an existing bucket.
+   *
+   * @param args KeyArgs
+   *
+   * @return InputStream
+   *
+   * @throws OzoneException
+   */
+  OutputStream newKeyWriter(KeyArgs args)
+      throws IOException, OzoneException;
+
+
+  /**
+   * Tells the file system that the object has been written out
+   * completely and it can do any house keeping operation that needs
+   * to be done.
+   *
+   * @param args Key Args
+   *
+   * @param stream
+   * @throws IOException
+   */
+  void commitKey(KeyArgs args, OutputStream stream)
+      throws IOException, OzoneException;
+
+
+  /**
+   * Reads a key from an existing bucket.
+   *
+   * @param args KeyArgs
+   *
+   * @return LengthInputStream
+   *
+   * @throws IOException
+   */
+  LengthInputStream newKeyReader(KeyArgs args)
+      throws IOException, OzoneException;
 
+
+  /**
+   * Deletes an existing key.
+   *
+   * @param args KeyArgs
+   *
+   * @throws OzoneException
+   */
+  void deleteKey(KeyArgs args) throws IOException, OzoneException;
+
+
+  /**
+   * Returns a list of Key.
+   *
+   * @param args KeyArgs
+   *
+   * @return BucketList
+   *
+   * @throws IOException
+   */
+  ListKeys listKeys(ListArgs args) throws IOException, OzoneException;
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ea0bb4a4/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/localstorage/LocalStorageHandler.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/localstorage/LocalStorageHandler.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/localstorage/LocalStorageHandler.java
index 9850551..edba688 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/localstorage/LocalStorageHandler.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/localstorage/LocalStorageHandler.java
@@ -20,28 +20,33 @@ package org.apache.hadoop.ozone.web.localstorage;
 
 import org.apache.hadoop.classification.InterfaceAudience;
 import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hdfs.server.datanode.fsdataset.LengthInputStream;
 import org.apache.hadoop.ozone.web.exceptions.OzoneException;
 import org.apache.hadoop.ozone.web.handlers.BucketArgs;
+import org.apache.hadoop.ozone.web.handlers.KeyArgs;
+import org.apache.hadoop.ozone.web.handlers.ListArgs;
 import org.apache.hadoop.ozone.web.handlers.UserArgs;
 import org.apache.hadoop.ozone.web.handlers.VolumeArgs;
 import org.apache.hadoop.ozone.web.interfaces.StorageHandler;
 import org.apache.hadoop.ozone.web.request.OzoneQuota;
 import org.apache.hadoop.ozone.web.response.BucketInfo;
 import org.apache.hadoop.ozone.web.response.ListBuckets;
+import org.apache.hadoop.ozone.web.response.ListKeys;
 import org.apache.hadoop.ozone.web.response.ListVolumes;
 import org.apache.hadoop.ozone.web.response.VolumeInfo;
 
 import java.io.IOException;
-
+import java.io.OutputStream;
 
 /**
- * PLEASE NOTE : This file is a dummy backend for test purposes
- * and prototyping effort only. It does not handle any Object semantics
- * correctly, neither does it take care of security.
+ * PLEASE NOTE : This file is a dummy backend for test purposes and prototyping
+ * effort only. It does not handle any Object semantics correctly, neither does
+ * it take care of security.
  */
 @InterfaceAudience.Private
 public class LocalStorageHandler implements StorageHandler {
   private final Configuration conf;
+
   /**
    * Constructs LocalStorageHandler.
    */
@@ -53,7 +58,6 @@ public class LocalStorageHandler implements StorageHandler {
    * Creates Storage Volume.
    *
    * @param args - volumeArgs
-   *
    * @throws IOException
    */
   @Override
@@ -68,7 +72,6 @@ public class LocalStorageHandler implements StorageHandler {
    * setVolumeOwner - sets the owner of the volume.
    *
    * @param args volumeArgs
-   *
    * @throws IOException
    */
   @Override
@@ -82,9 +85,8 @@ public class LocalStorageHandler implements StorageHandler {
   /**
    * Set Volume Quota Info.
    *
-   * @param args - volumeArgs
+   * @param args   - volumeArgs
    * @param remove - true if the request is to remove the quota
-   *
    * @throws IOException
    */
   @Override
@@ -93,23 +95,19 @@ public class LocalStorageHandler implements StorageHandler {
     OzoneMetadataManager oz =
         OzoneMetadataManager.getOzoneMetadataManager(conf);
 
-    if(remove) {
+    if (remove) {
       OzoneQuota quota = new OzoneQuota();
       args.setQuota(quota);
     }
     oz.setVolumeProperty(args, OzoneMetadataManager.VolumeProperty.QUOTA);
   }
 
-
   /**
-   * Checks if a Volume exists and the user specified has access to the
-   * volume.
+   * Checks if a Volume exists and the user specified has access to the volume.
    *
    * @param args - volumeArgs
-   *
-   * @return - Boolean - True if the user can modify the volume.
-   * This is possible for owners of the volume and admin users
-   *
+   * @return - Boolean - True if the user can modify the volume. This is
+   * possible for owners of the volume and admin users
    * @throws IOException
    */
   @Override
@@ -120,14 +118,11 @@ public class LocalStorageHandler implements StorageHandler {
     return oz.checkVolumeAccess(args);
   }
 
-
   /**
    * Returns Info about the specified Volume.
    *
    * @param args - volumeArgs
-   *
    * @return VolumeInfo
-   *
    * @throws IOException
    */
   @Override
@@ -138,12 +133,10 @@ public class LocalStorageHandler implements StorageHandler {
     return oz.getVolumeInfo(args);
   }
 
-
   /**
    * Deletes an Empty Volume.
    *
    * @param args - Volume Args
-   *
    * @throws IOException
    */
   @Override
@@ -158,9 +151,7 @@ public class LocalStorageHandler implements StorageHandler {
    * Returns the List of Volumes owned by the specific user.
    *
    * @param args - UserArgs
-   *
    * @return - List of Volumes
-   *
    * @throws IOException
    */
   @Override
@@ -172,11 +163,10 @@ public class LocalStorageHandler implements StorageHandler {
   }
 
   /**
-   * true if the bucket exists and user has read access
-   * to the bucket else throws Exception.
+   * true if the bucket exists and user has read access to the bucket else
+   * throws Exception.
    *
    * @param args Bucket args structure
-   *
    * @throws IOException
    */
   @Override
@@ -189,7 +179,6 @@ public class LocalStorageHandler implements StorageHandler {
    * Creates a Bucket in specified Volume.
    *
    * @param args BucketArgs- BucketName, UserName and Acls
-   *
    * @throws IOException
    */
   @Override
@@ -203,7 +192,6 @@ public class LocalStorageHandler implements StorageHandler {
    * Adds or Removes ACLs from a Bucket.
    *
    * @param args - BucketArgs
-   *
    * @throws IOException
    */
   @Override
@@ -218,7 +206,6 @@ public class LocalStorageHandler implements StorageHandler {
    * Enables or disables Bucket Versioning.
    *
    * @param args - BucketArgs
-   *
    * @throws IOException
    */
   @Override
@@ -234,7 +221,6 @@ public class LocalStorageHandler implements StorageHandler {
    * Sets the Storage Class of a Bucket.
    *
    * @param args - BucketArgs
-   *
    * @throws IOException
    */
   @Override
@@ -250,7 +236,6 @@ public class LocalStorageHandler implements StorageHandler {
    * Deletes a bucket if it is empty.
    *
    * @param args Bucket args structure
-   *
    * @throws IOException
    */
   @Override
@@ -264,9 +249,7 @@ public class LocalStorageHandler implements StorageHandler {
    * Returns all Buckets of a specified Volume.
    *
    * @param args --User Args
-   *
    * @return ListAllBuckets
-   *
    * @throws OzoneException
    */
   @Override
@@ -281,9 +264,7 @@ public class LocalStorageHandler implements StorageHandler {
    * Returns Bucket's Metadata as a String.
    *
    * @param args Bucket args structure
-   *
    * @return Info about the bucket
-   *
    * @throws IOException
    */
   @Override
@@ -293,4 +274,68 @@ public class LocalStorageHandler implements StorageHandler {
         OzoneMetadataManager.getOzoneMetadataManager(conf);
     return oz.getBucketInfo(args);
   }
+
+  /**
+   * Writes a key in an existing bucket.
+   *
+   * @param args KeyArgs
+   * @return InputStream
+   * @throws OzoneException
+   */
+  @Override
+  public OutputStream newKeyWriter(KeyArgs args) throws IOException,
+      OzoneException {
+    return null;
+  }
+
+  /**
+   * Tells the file system that the object has been written out completely and
+   * it can do any house keeping operation that needs to be done.
+   *
+   * @param args   Key Args
+   * @param stream
+   * @throws IOException
+   */
+  @Override
+  public void commitKey(KeyArgs args, OutputStream stream) throws
+      IOException, OzoneException {
+
+  }
+
+  /**
+   * Reads a key from an existing bucket.
+   *
+   * @param args KeyArgs
+   * @return LengthInputStream
+   * @throws IOException
+   */
+  @Override
+  public LengthInputStream newKeyReader(KeyArgs args) throws IOException,
+      OzoneException {
+    return null;
+  }
+
+  /**
+   * Deletes an existing key.
+   *
+   * @param args KeyArgs
+   * @throws OzoneException
+   */
+  @Override
+  public void deleteKey(KeyArgs args) throws IOException, OzoneException {
+
+  }
+
+  /**
+   * Returns a list of Key.
+   *
+   * @param args KeyArgs
+   * @return BucketList
+   * @throws IOException
+   */
+  @Override
+  public ListKeys listKeys(ListArgs args) throws IOException, OzoneException {
+    return null;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/ea0bb4a4/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/storage/DistributedStorageHandler.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/storage/DistributedStorageHandler.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/storage/DistributedStorageHandler.java
index 75fad53..9cb8430 100644
--- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/storage/DistributedStorageHandler.java
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/storage/DistributedStorageHandler.java
@@ -18,18 +18,23 @@
 
 package org.apache.hadoop.ozone.web.storage;
 
-import java.io.IOException;
-
+import org.apache.hadoop.hdfs.server.datanode.fsdataset.LengthInputStream;
 import org.apache.hadoop.ozone.web.exceptions.OzoneException;
 import org.apache.hadoop.ozone.web.handlers.BucketArgs;
+import org.apache.hadoop.ozone.web.handlers.KeyArgs;
+import org.apache.hadoop.ozone.web.handlers.ListArgs;
 import org.apache.hadoop.ozone.web.handlers.UserArgs;
 import org.apache.hadoop.ozone.web.handlers.VolumeArgs;
 import org.apache.hadoop.ozone.web.interfaces.StorageHandler;
 import org.apache.hadoop.ozone.web.response.BucketInfo;
 import org.apache.hadoop.ozone.web.response.ListBuckets;
+import org.apache.hadoop.ozone.web.response.ListKeys;
 import org.apache.hadoop.ozone.web.response.ListVolumes;
 import org.apache.hadoop.ozone.web.response.VolumeInfo;
 
+import java.io.IOException;
+import java.io.OutputStream;
+
 /**
  * A {@link StorageHandler} implementation that distributes object storage
  * across the nodes of an HDFS cluster.
@@ -125,4 +130,67 @@ public final class DistributedStorageHandler implements StorageHandler {
       throws IOException, OzoneException {
     return null;
   }
+
+  /**
+   * Writes a key in an existing bucket.
+   *
+   * @param args KeyArgs
+   * @return InputStream
+   * @throws OzoneException
+   */
+  @Override
+  public OutputStream newKeyWriter(KeyArgs args) throws IOException,
+      OzoneException {
+    return null;
+  }
+
+  /**
+   * Tells the file system that the object has been written out completely and
+   * it can do any house keeping operation that needs to be done.
+   *
+   * @param args   Key Args
+   * @param stream
+   * @throws IOException
+   */
+  @Override
+  public void commitKey(KeyArgs args, OutputStream stream) throws
+      IOException, OzoneException {
+
+  }
+
+  /**
+   * Reads a key from an existing bucket.
+   *
+   * @param args KeyArgs
+   * @return LengthInputStream
+   * @throws IOException
+   */
+  @Override
+  public LengthInputStream newKeyReader(KeyArgs args) throws IOException,
+      OzoneException {
+    return null;
+  }
+
+  /**
+   * Deletes an existing key.
+   *
+   * @param args KeyArgs
+   * @throws OzoneException
+   */
+  @Override
+  public void deleteKey(KeyArgs args) throws IOException, OzoneException {
+
+  }
+
+  /**
+   * Returns a list of Key.
+   *
+   * @param args KeyArgs
+   * @return BucketList
+   * @throws IOException
+   */
+  @Override
+  public ListKeys listKeys(ListArgs args) throws IOException, OzoneException {
+    return null;
+  }
 }


[2/2] hadoop git commit: HDFS-9916. OzoneHandler : Add Key handler. Contributed by Anu Engineer.

Posted by cn...@apache.org.
HDFS-9916. OzoneHandler : Add Key handler. Contributed by Anu Engineer.


Project: http://git-wip-us.apache.org/repos/asf/hadoop/repo
Commit: http://git-wip-us.apache.org/repos/asf/hadoop/commit/28f770d8
Tree: http://git-wip-us.apache.org/repos/asf/hadoop/tree/28f770d8
Diff: http://git-wip-us.apache.org/repos/asf/hadoop/diff/28f770d8

Branch: refs/heads/HDFS-7240
Commit: 28f770d8b0ead12d0d80bc4dfcb29d5e5eb5f380
Parents: ea0bb4a
Author: Chris Nauroth <cn...@apache.org>
Authored: Wed Mar 9 10:20:24 2016 -0800
Committer: Chris Nauroth <cn...@apache.org>
Committed: Wed Mar 9 10:20:24 2016 -0800

----------------------------------------------------------------------
 .../hadoop/ozone/web/handlers/KeyArgs.java      | 125 +++++++++
 .../hadoop/ozone/web/handlers/KeyHandler.java   | 212 +++++++++++++++
 .../ozone/web/handlers/KeyProcessTemplate.java  | 208 +++++++++++++++
 .../hadoop/ozone/web/handlers/ListArgs.java     | 106 ++++++++
 .../hadoop/ozone/web/interfaces/Accounting.java |  57 ++++
 .../hadoop/ozone/web/interfaces/Keys.java       | 118 +++++++++
 .../LengthInputStreamMessageBodyWriter.java     |  59 +++++
 .../hadoop/ozone/web/response/KeyInfo.java      | 261 +++++++++++++++++++
 .../hadoop/ozone/web/response/ListKeys.java     | 183 +++++++++++++
 9 files changed, 1329 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/28f770d8/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyArgs.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyArgs.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyArgs.java
new file mode 100644
index 0000000..754c333
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyArgs.java
@@ -0,0 +1,125 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.web.handlers;
+
+/**
+ * Class that packages all key Arguments.
+ */
+public class KeyArgs extends BucketArgs {
+  private String key;
+  private boolean delete;
+  private String hash;
+  private long size;
+
+  /**
+   * Constructor for Key Args.
+   *
+   * @param volumeName - Volume Name
+   * @param bucketName - Bucket Name
+   * @param objectName - Key
+   */
+  public KeyArgs(String volumeName, String bucketName,
+                 String objectName, UserArgs args) {
+    super(volumeName, bucketName, args);
+    this.key = objectName;
+  }
+
+  /**
+   * Get Key Name.
+   *
+   * @return String
+   */
+  public String getKeyName() {
+    return this.key;
+  }
+
+  /**
+   * Checks if this request is for a Delete key.
+   *
+   * @return boolean
+   */
+  public boolean isDelete() {
+    return delete;
+  }
+
+  /**
+   * Sets the key request as a Delete Request.
+   *
+   * @param delete bool, indicating if this is a delete request
+   */
+  public void setDelete(boolean delete) {
+    this.delete = delete;
+  }
+
+  /**
+   * Computed File hash.
+   *
+   * @return String
+   */
+  public String getHash() {
+    return hash;
+  }
+
+  /**
+   * Sets the hash String.
+   *
+   * @param hash String
+   */
+  public void setHash(String hash) {
+    this.hash = hash;
+  }
+
+  /**
+   * Returns the file size.
+   *
+   * @return long - file size
+   */
+  public long getSize() {
+    return size;
+  }
+
+  /**
+   * Set Size.
+   *
+   * @param size Size of the file
+   */
+  public void setSize(long size) {
+    this.size = size;
+  }
+
+  /**
+   * Returns the name of the resource.
+   *
+   * @return String
+   */
+  @Override
+  public String getResourceName() {
+    return super.getResourceName() + "/" + getKeyName();
+  }
+
+  /**
+   * Parent name of this resource.
+   *
+   * @return String.
+   */
+  @Override
+  public String getParentName() {
+    return super.getResourceName();
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/28f770d8/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyHandler.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyHandler.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyHandler.java
new file mode 100644
index 0000000..bf0643e
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyHandler.java
@@ -0,0 +1,212 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.web.handlers;
+
+import org.apache.commons.codec.binary.Hex;
+import org.apache.hadoop.hdfs.server.datanode.fsdataset.LengthInputStream;
+import org.apache.hadoop.ozone.web.exceptions.OzoneException;
+import org.apache.hadoop.ozone.web.interfaces.Keys;
+import org.apache.hadoop.ozone.web.interfaces.StorageHandler;
+import org.apache.hadoop.ozone.web.utils.OzoneUtils;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+import static java.net.HttpURLConnection.HTTP_CREATED;
+import static java.net.HttpURLConnection.HTTP_OK;
+
+/**
+ * KeyHandler deals with basic Key Operations.
+ */
+public class KeyHandler implements Keys {
+
+  /**
+   * Gets the Key if it exists.
+   *
+   * @param volume  Storage Volume
+   * @param bucket  Name of the bucket
+   * @param req     Request
+   * @param info    - UriInfo
+   * @param headers Http Header
+   * @return Response
+   * @throws OzoneException
+   */
+  @Override
+  public Response getKey(String volume, String bucket, String key,
+                         Request req, UriInfo info, HttpHeaders headers)
+      throws OzoneException {
+    return new KeyProcessTemplate() {
+      /**
+       * Abstract function that gets implemented in the KeyHandler functions.
+       * This function will just deal with the core file system related logic
+       * and will rely on handleCall function for repetitive error checks
+       *
+       * @param args - parsed bucket args, name, userName, ACLs etc
+       * @param input - The body as an Input Stream
+       * @param request - Http request
+       * @param headers - Parsed http Headers.
+       * @param info - UriInfo
+       *
+       * @return Response
+       *
+       * @throws IOException - From the file system operations
+       */
+      @Override
+      public Response doProcess(KeyArgs args, InputStream input,
+                                Request request, HttpHeaders headers,
+                                UriInfo info)
+          throws IOException, OzoneException, NoSuchAlgorithmException {
+        StorageHandler fs = StorageHandlerBuilder.getStorageHandler();
+        LengthInputStream stream = fs.newKeyReader(args);
+        return OzoneUtils.getResponse(args, HTTP_OK, stream);
+      }
+    }.handleCall(volume, bucket, key, req, headers, info, null);
+  }
+
+  /**
+   * Adds a key to an existing bucket. If the object already exists this call
+   * will overwrite or add with new version number if the bucket versioning is
+   * turned on.
+   *
+   * @param volume  Storage Volume Name
+   * @param bucket  Name of the bucket
+   * @param keys    Name of the Object
+   * @param is      InputStream or File Data
+   * @param req     Request
+   * @param info    - UriInfo
+   * @param headers http headers
+   * @return Response
+   * @throws OzoneException
+   */
+  @Override
+  public Response putKey(String volume, String bucket, String keys,
+                         InputStream is, Request req, UriInfo info,
+                         HttpHeaders headers) throws OzoneException {
+
+    return new KeyProcessTemplate() {
+      /**
+       * Abstract function that gets implemented in the KeyHandler functions.
+       * This function will just deal with the core file system related logic
+       * and will rely on handleCall function for repetitive error checks
+       *
+       * @param args - parsed bucket args, name, userName, ACLs etc
+       * @param input - The body as an Input Stream
+       * @param request - Http request
+       * @param headers - Parsed http Headers.
+       * @param info - UriInfo
+       *
+       * @return Response
+       *
+       * @throws IOException - From the file system operations
+       */
+      @Override
+      public Response doProcess(KeyArgs args, InputStream input,
+                                Request request, HttpHeaders headers,
+                                UriInfo info)
+          throws IOException, OzoneException, NoSuchAlgorithmException {
+        final int eof = -1;
+        StorageHandler fs = StorageHandlerBuilder.getStorageHandler();
+
+        byte[] buffer = new byte[4 * 1024];
+        String contentLenString = getContentLength(headers, args);
+        String newLen = contentLenString.replaceAll("\"", "");
+        int contentLen = Integer.parseInt(newLen);
+
+        MessageDigest md5 = MessageDigest.getInstance("MD5");
+        int bytesRead = 0;
+        int len = 0;
+        OutputStream stream = fs.newKeyWriter(args);
+        while ((bytesRead < contentLen) && (len != eof)) {
+          int readSize =
+              (contentLen - bytesRead > buffer.length) ? buffer.length :
+                  contentLen - bytesRead;
+          len = input.read(buffer, 0, readSize);
+          if (len != eof) {
+            stream.write(buffer, 0, len);
+            md5.update(buffer, 0, len);
+            bytesRead += len;
+
+          }
+        }
+
+        checkFileLengthMatch(args, fs, contentLen, bytesRead);
+
+        String hashString = Hex.encodeHexString(md5.digest());
+// TODO : Enable hash value checking.
+//          String contentHash = getContentMD5(headers, args);
+//          checkFileHashMatch(args, hashString, fs, contentHash);
+        args.setHash(hashString);
+        args.setSize(bytesRead);
+        fs.commitKey(args, stream);
+        return OzoneUtils.getResponse(args, HTTP_CREATED, "");
+      }
+    }.handleCall(volume, bucket, keys, req, headers, info, is);
+  }
+
+  /**
+   * Deletes an existing key.
+   *
+   * @param volume  Storage Volume Name
+   * @param bucket  Name of the bucket
+   * @param keys    Name of the Object
+   * @param req     http Request
+   * @param info    - UriInfo
+   * @param headers HttpHeaders
+   * @return Response
+   * @throws OzoneException
+   */
+  @Override
+  public Response deleteKey(String volume, String bucket, String keys,
+                            Request req, UriInfo info, HttpHeaders headers)
+      throws OzoneException {
+    return new KeyProcessTemplate() {
+      /**
+       * Abstract function that gets implemented in the KeyHandler functions.
+       * This function will just deal with the core file system related logic
+       * and will rely on handleCall function for repetitive error checks
+       *
+       * @param args - parsed bucket args, name, userName, ACLs etc
+       * @param input - The body as an Input Stream
+       * @param request - Http request
+       * @param headers - Parsed http Headers.
+       * @param info - UriInfo
+       *
+       * @return Response
+       *
+       * @throws IOException - From the file system operations
+       */
+      @Override
+      public Response doProcess(KeyArgs args, InputStream input,
+                                Request request, HttpHeaders headers,
+                                UriInfo info)
+          throws IOException, OzoneException, NoSuchAlgorithmException {
+        StorageHandler fs = StorageHandlerBuilder.getStorageHandler();
+        fs.deleteKey(args);
+        return OzoneUtils.getResponse(args, HTTP_OK, "");
+      }
+    }.handleCall(volume, bucket, keys, req, headers, info, null);
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/28f770d8/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyProcessTemplate.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyProcessTemplate.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyProcessTemplate.java
new file mode 100644
index 0000000..7607434
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/KeyProcessTemplate.java
@@ -0,0 +1,208 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.web.handlers;
+
+import org.apache.commons.codec.binary.Base64;
+import org.apache.hadoop.ozone.web.exceptions.ErrorTable;
+import org.apache.hadoop.ozone.web.exceptions.OzoneException;
+import org.apache.hadoop.ozone.web.headers.Header;
+import org.apache.hadoop.ozone.web.interfaces.StorageHandler;
+import org.apache.hadoop.ozone.web.interfaces.UserAuth;
+import org.apache.hadoop.ozone.web.utils.OzoneUtils;
+
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+
+import static org.apache.hadoop.ozone.web.exceptions.ErrorTable.BAD_DIGEST;
+import static org.apache.hadoop.ozone.web.exceptions.ErrorTable.INCOMPLETE_BODY;
+import static org.apache.hadoop.ozone.web.exceptions.ErrorTable.INVALID_BUCKET_NAME;
+import static org.apache.hadoop.ozone.web.exceptions.ErrorTable.INVALID_REQUEST;
+import static org.apache.hadoop.ozone.web.exceptions.ErrorTable.SERVER_ERROR;
+import static org.apache.hadoop.ozone.web.exceptions.ErrorTable.newError;
+
+/**
+ * This class abstracts way the repetitive tasks in  Key handling code.
+ */
+public abstract class KeyProcessTemplate {
+
+  /**
+   * This function serves as the common error handling function for all Key
+   * related operations.
+   *
+   * @param bucket  bucket Name
+   * @param key     the object name
+   * @param headers Http headers
+   * @param is      Input XML stream
+   * @throws OzoneException
+   */
+  public Response handleCall(String volume, String bucket, String key,
+                             Request request, HttpHeaders headers, UriInfo info,
+                             InputStream is) throws OzoneException {
+
+    String reqID = OzoneUtils.getRequestID();
+    String hostName = OzoneUtils.getHostName();
+    UserArgs userArgs = null;
+    try {
+      OzoneUtils.validate(request, headers, reqID, bucket, hostName);
+      OzoneUtils.verifyBucketName(bucket);
+
+      UserAuth auth = UserHandlerBuilder.getAuthHandler();
+      userArgs = new UserArgs(reqID, hostName, request, info, headers);
+      userArgs.setUserName(auth.getUser(userArgs));
+
+      KeyArgs args = new KeyArgs(volume, bucket, key, userArgs);
+      return doProcess(args, is, request, headers, info);
+    } catch (IllegalArgumentException argExp) {
+      OzoneException ex =
+          newError(INVALID_BUCKET_NAME, reqID, bucket, hostName);
+      ex.setMessage(argExp.getMessage());
+      throw ex;
+    } catch (IOException fsExp) {
+      // TODO : Handle errors from the FileSystem , let us map to server error
+      // for now.
+      throw ErrorTable.newError(ErrorTable.SERVER_ERROR, userArgs, fsExp);
+    } catch (NoSuchAlgorithmException algoEx) {
+      OzoneException ex =
+          ErrorTable.newError(SERVER_ERROR, reqID, key, hostName);
+      ex.setMessage(algoEx.getMessage());
+      throw ex;
+    }
+  }
+
+  /**
+   * Abstract function that gets implemented in the KeyHandler functions. This
+   * function will just deal with the core file system related logic and will
+   * rely on handleCall function for repetitive error checks
+   *
+   * @param args    - parsed bucket args, name, userName, ACLs etc
+   * @param input   - The body as an Input Stream
+   * @param request - Http request
+   * @param headers - Parsed http Headers.
+   * @param info    - UriInfo
+   * @return Response
+   * @throws IOException - From the file system operations
+   */
+  public abstract Response doProcess(KeyArgs args, InputStream input,
+                                     Request request, HttpHeaders headers,
+                                     UriInfo info)
+      throws IOException, OzoneException, NoSuchAlgorithmException;
+
+  /**
+   * checks if the File Content-MD5 we wrote matches the hash we computed from
+   * the stream. if it does match we delete the file and throw and exception to
+   * let the user know that we have a hash mismatch
+   *
+   * @param args           Object Args
+   * @param computedString MD5 hash value
+   * @param fs             Pointer to File System so we can delete the file
+   * @param contentHash    User Specified hash string
+   * @throws IOException
+   * @throws OzoneException
+   */
+  public void checkFileHashMatch(KeyArgs args, String computedString,
+                                 StorageHandler fs, String contentHash)
+      throws IOException, OzoneException {
+    if (contentHash != null) {
+      String contentString =
+          new String(Base64.decodeBase64(contentHash), OzoneUtils.ENCODING)
+              .trim();
+
+      if (!contentString.equals(computedString)) {
+        fs.deleteKey(args);
+        OzoneException ex = ErrorTable.newError(BAD_DIGEST, args.getRequestID(),
+            args.getKeyName(), args.getHostName());
+        ex.setMessage(String.format("MD5 Digest mismatch. Expected %s Found " +
+            "%s", contentString, computedString));
+        throw ex;
+      }
+    }
+  }
+
+  /**
+   * check if the content-length matches the actual stream length. if we find a
+   * mismatch we will delete the file and throw an exception to let the user
+   * know that length mismatch detected
+   *
+   * @param args       Object Args
+   * @param fs         Pointer to File System Object, to delete the file that we
+   *                   wrote
+   * @param contentLen Http Content-Length Header
+   * @param bytesRead  Actual Bytes we read from the stream
+   * @throws IOException
+   * @throws OzoneException
+   */
+  public void checkFileLengthMatch(KeyArgs args, StorageHandler fs,
+                                   int contentLen, int bytesRead)
+      throws IOException, OzoneException {
+    if (bytesRead != contentLen) {
+      fs.deleteKey(args);
+      OzoneException ex = ErrorTable.newError(INCOMPLETE_BODY,
+          args.getRequestID(), args.getKeyName(), args.getHostName());
+      ex.setMessage(String.format("Body length mismatch. Expected length : %d" +
+          " Found %d", contentLen, bytesRead));
+      throw ex;
+    }
+  }
+
+  /**
+   * Returns Content Length header value if available.
+   *
+   * @param headers - Http Headers
+   * @return - String or null
+   */
+  public String getContentLength(HttpHeaders headers, KeyArgs args)
+      throws OzoneException {
+    List<String> contentLengthList =
+        headers.getRequestHeader(HttpHeaders.CONTENT_LENGTH);
+    if ((contentLengthList != null) && (contentLengthList.size() > 0)) {
+      return contentLengthList.get(0);
+    }
+
+    OzoneException ex = ErrorTable.newError(INVALID_REQUEST, args);
+    ex.setMessage("Content-Length is a required header for putting a key.");
+    throw ex;
+
+  }
+
+  /**
+   * Returns Content MD5 value if available.
+   *
+   * @param headers - Http Headers
+   * @return - String or null
+   */
+  public String getContentMD5(HttpHeaders headers, KeyArgs args) {
+    List<String> contentLengthList =
+        headers.getRequestHeader(Header.CONTENT_MD5);
+    if ((contentLengthList != null) && (contentLengthList.size() > 0)) {
+      return contentLengthList.get(0);
+    }
+// TODO : Should we make this compulsory ?
+//    OzoneException ex = ErrorTable.newError(ErrorTable.invalidRequest, args);
+//    ex.setMessage("Content-MD5 is a required header for putting a key");
+//    throw ex;
+    return "";
+  }
+}
+

http://git-wip-us.apache.org/repos/asf/hadoop/blob/28f770d8/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/ListArgs.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/ListArgs.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/ListArgs.java
new file mode 100644
index 0000000..892b97a
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/handlers/ListArgs.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.hadoop.ozone.web.handlers;
+
+/**
+ * Supports listing keys with pagination.
+ */
+public class ListArgs extends BucketArgs {
+  private String startPage;
+  private String prefix;
+  private int maxKeys;
+
+  /**
+   * Constructor for ListArgs.
+   *
+   * @param args      - BucketArgs
+   * @param prefix    Prefix to start Query from
+   * @param maxKeys   Max result set
+   * @param startPage - Page token
+   */
+  public ListArgs(BucketArgs args, String prefix, int maxKeys,
+                  String startPage) {
+    super(args);
+    setPrefix(prefix);
+    setMaxKeys(maxKeys);
+    setStartPage(startPage);
+  }
+
+  /**
+   * Copy Constructor for ListArgs.
+   *
+   * @param args - List Args
+   */
+  public ListArgs(ListArgs args) {
+    this(args, args.getPrefix(), args.getMaxKeys(), args.getStartPage());
+  }
+
+  /**
+   * Returns page token.
+   *
+   * @return String
+   */
+  public String getStartPage() {
+    return startPage;
+  }
+
+  /**
+   * Sets page token.
+   *
+   * @param startPage - Page token
+   */
+  public void setStartPage(String startPage) {
+    this.startPage = startPage;
+  }
+
+  /**
+   * Gets max keys.
+   *
+   * @return int
+   */
+  public int getMaxKeys() {
+    return maxKeys;
+  }
+
+  /**
+   * Sets max keys.
+   *
+   * @param maxKeys - Maximum keys to return
+   */
+  public void setMaxKeys(int maxKeys) {
+    this.maxKeys = maxKeys;
+  }
+
+  /**
+   * Gets prefix.
+   *
+   * @return String
+   */
+  public String getPrefix() {
+    return prefix;
+  }
+
+  /**
+   * Sets prefix.
+   *
+   * @param prefix - The prefix that we are looking for
+   */
+  public void setPrefix(String prefix) {
+    this.prefix = prefix;
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/hadoop/blob/28f770d8/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/Accounting.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/Accounting.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/Accounting.java
new file mode 100644
index 0000000..f03276c
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/Accounting.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.web.interfaces;
+
+/**
+ * This in the accounting interface, Ozone Rest interface will call into this
+ * interface whenever a put or delete key happens.
+ * <p>
+ * TODO : Technically we need to report bucket creation and deletion too
+ * since the bucket names and metadata consume storage.
+ * <p>
+ * TODO : We should separate out reporting metadata & data --
+ * <p>
+ * In some cases end users will only want to account for the data they are
+ * storing since metadata is mostly a cost of business.
+ */
+public interface Accounting {
+  /**
+   * This call is made when ever a put key call is made.
+   * <p>
+   * In case of a Put which causes a over write of a key accounting system will
+   * see two calls, a removeByte call followed by an addByte call.
+   *
+   * @param owner  - Volume Owner
+   * @param volume - Name of the Volume
+   * @param bucket - Name of the bucket
+   * @param bytes  - How many bytes are put
+   */
+  void addBytes(String owner, String volume, String bucket, int bytes);
+
+  /**
+   * This call is made whenever a delete call is made.
+   *
+   * @param owner  - Volume Owner
+   * @param volume - Name of the Volume
+   * @param bucket - Name of the bucket
+   * @param bytes  - How many bytes are deleted
+   */
+  void removeBytes(String owner, String volume, String bucket, int bytes);
+
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/28f770d8/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/Keys.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/Keys.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/Keys.java
new file mode 100644
index 0000000..644ba62
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/interfaces/Keys.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.web.interfaces;
+
+import org.apache.hadoop.ozone.web.exceptions.OzoneException;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Request;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.UriInfo;
+import java.io.InputStream;
+
+/**
+ * This interface defines operations permitted on a key.
+ */
+
+@Path("/{volume}/{bucket}/{keys}")
+public interface Keys {
+
+  /**
+   * Adds a key to an existing bucket. If the object already exists
+   * this call will overwrite or add with new version number if the bucket
+   * versioning is turned on.
+   *
+   * @param volume Storage Volume Name
+   * @param bucket Name of the bucket
+   * @param keys Name of the Object
+   * @param is InputStream or File Data
+   * @param req Request
+   * @param headers http headers
+   *
+   * @return Response
+   *
+   * @throws OzoneException
+   */
+  @PUT
+  @Consumes(MediaType.WILDCARD)
+  Response putKey(@PathParam("volume") String volume,
+                  @PathParam("bucket") String bucket,
+                  @PathParam("keys") String keys,
+                  InputStream is,
+                  @Context Request req,
+                  @Context UriInfo info,
+                  @Context HttpHeaders headers)
+    throws OzoneException;
+
+
+  /**
+   * Gets the Key if it exists.
+   *
+   * @param volume Storage Volume
+   * @param bucket Name of the bucket
+   * @param keys Object Name
+   * @param req Request
+   * @param headers Http Header
+   *
+   * @return Response
+   *
+   * @throws OzoneException
+   */
+  @GET
+  @Produces(MediaType.APPLICATION_OCTET_STREAM)
+  Response getKey(@PathParam("volume") String volume,
+                  @PathParam("bucket") String bucket,
+                  @PathParam("keys") String keys,
+                  @Context Request req,
+                  @Context UriInfo info,
+                  @Context HttpHeaders headers)
+    throws OzoneException;
+
+  /**
+   * Deletes an existing key.
+   *
+   * @param volume Storage Volume Name
+   * @param bucket Name of the bucket
+   * @param keys Name of the Object
+   * @param req http Request
+   * @param headers HttpHeaders
+   *
+   * @return Response
+   *
+   * @throws OzoneException
+   */
+  @DELETE
+  Response deleteKey(@PathParam("volume") String volume,
+                     @PathParam("bucket") String bucket,
+                     @PathParam("keys") String keys,
+                     @Context Request req,
+                     @Context UriInfo info,
+                     @Context HttpHeaders headers)
+    throws OzoneException;
+}
+

http://git-wip-us.apache.org/repos/asf/hadoop/blob/28f770d8/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/messages/LengthInputStreamMessageBodyWriter.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/messages/LengthInputStreamMessageBodyWriter.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/messages/LengthInputStreamMessageBodyWriter.java
new file mode 100644
index 0000000..502ccd5
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/messages/LengthInputStreamMessageBodyWriter.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+
+package org.apache.hadoop.ozone.web.messages;
+
+import org.apache.hadoop.hdfs.server.datanode.fsdataset.LengthInputStream;
+import org.apache.hadoop.io.IOUtils;
+
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.ext.MessageBodyWriter;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
+
+/**
+ * Writes outbound HTTP response object bytes.  The content length is determined
+ * from the {@link LengthInputStream}.
+ */
+public final class LengthInputStreamMessageBodyWriter
+    implements MessageBodyWriter<LengthInputStream> {
+  private static final int CHUNK_SIZE = 8192;
+
+  @Override
+  public long getSize(LengthInputStream lis, Class<?> type, Type genericType,
+                      Annotation[] annotations, MediaType mediaType) {
+    return lis.getLength();
+  }
+
+  @Override
+  public boolean isWriteable(Class<?> type, Type genericType,
+                             Annotation[] annotations, MediaType mediaType) {
+    return LengthInputStream.class.isAssignableFrom(type);
+  }
+
+  @Override
+  public void writeTo(LengthInputStream lis, Class<?> type, Type genericType,
+                      Annotation[] annotations, MediaType mediaType,
+                      MultivaluedMap<String, Object> httpHeaders,
+                      OutputStream out) throws IOException {
+    IOUtils.copyBytes(lis, out, CHUNK_SIZE);
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/28f770d8/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfo.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfo.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfo.java
new file mode 100644
index 0000000..7e9e00f
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/response/KeyInfo.java
@@ -0,0 +1,261 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.hadoop.ozone.web.response;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonMethod;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.ObjectWriter;
+import org.codehaus.jackson.map.annotate.JsonFilter;
+import org.codehaus.jackson.map.ser.FilterProvider;
+import org.codehaus.jackson.map.ser.impl.SimpleBeanPropertyFilter;
+import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider;
+
+import java.io.IOException;
+
+/**
+ * Represents an Ozone key Object.
+ */
+public class KeyInfo implements Comparable<KeyInfo> {
+  static final String OBJECT_INFO = "OBJECT_INFO_FILTER";
+  /**
+   * This class allows us to create custom filters
+   * for the Json serialization.
+   */
+  @JsonFilter(OBJECT_INFO)
+  class MixIn {
+
+  }
+  private long version;
+  private String md5hash;
+  private String createdOn;
+  private long size;
+  private String keyName;
+
+  private String dataFileName;
+
+  /**
+   * When this key was created.
+   *
+   * @return Date String
+   */
+  public String getCreatedOn() {
+    return createdOn;
+  }
+
+  /**
+   * When this key was created.
+   *
+   * @param createdOn - Date String
+   */
+  public void setCreatedOn(String createdOn) {
+    this.createdOn = createdOn;
+  }
+
+  /**
+   * Full path to where the actual data for this key is stored.
+   *
+   * @return String
+   */
+  public String getDataFileName() {
+    return dataFileName;
+  }
+
+  /**
+   * Sets up where the file path is stored.
+   *
+   * @param dataFileName - Data File Name
+   */
+  public void setDataFileName(String dataFileName) {
+    this.dataFileName = dataFileName;
+  }
+
+  /**
+   * Gets the Keyname of this object.
+   *
+   * @return String
+   */
+  public String getKeyName() {
+    return keyName;
+  }
+
+  /**
+   * Sets the Key name of this object.
+   *
+   * @param keyName - String
+   */
+  public void setKeyName(String keyName) {
+    this.keyName = keyName;
+  }
+
+  /**
+   * Returns the MD5 Hash for the data of this key.
+   *
+   * @return String MD5
+   */
+  public String getMd5hash() {
+    return md5hash;
+  }
+
+  /**
+   * Sets the MD5 of this file.
+   *
+   * @param md5hash - Md5 of this file
+   */
+  public void setMd5hash(String md5hash) {
+    this.md5hash = md5hash;
+  }
+
+  /**
+   * Number of bytes stored in the data part of this key.
+   *
+   * @return long size of the data file
+   */
+  public long getSize() {
+    return size;
+  }
+
+  /**
+   * Sets the size of the Data part of this key.
+   *
+   * @param size - Size in long
+   */
+  public void setSize(long size) {
+    this.size = size;
+  }
+
+  /**
+   * Version of this key.
+   *
+   * @return - returns the version of this key.
+   */
+  public long getVersion() {
+    return version;
+  }
+
+  /**
+   * Sets the version of this key.
+   *
+   * @param version - Version String
+   */
+  public void setVersion(long version) {
+    this.version = version;
+  }
+
+  /**
+   * Compares this object with the specified object for order.  Returns a
+   * negative integer, zero, or a positive integer as this object is less
+   * than, equal to, or greater than the specified object.
+   *
+   * @param o the object to be compared.
+   *
+   * @return a negative integer, zero, or a positive integer as this object
+   * is less than, equal to, or greater than the specified object.
+   *
+   * @throws NullPointerException if the specified object is null
+   * @throws ClassCastException if the specified object's type prevents it
+   * from being compared to this object.
+   */
+  @Override
+  public int compareTo(KeyInfo o) {
+    if (this.keyName.compareTo(o.getKeyName()) != 0) {
+      return this.keyName.compareTo(o.getKeyName());
+    }
+
+    if (this.getVersion() == o.getVersion()) {
+      return 0;
+    }
+    if (this.getVersion() < o.getVersion()) {
+      return -1;
+    }
+    return 1;
+  }
+
+  @Override
+  public boolean equals(Object o) {
+    if (this == o) {
+      return true;
+    }
+
+    if (o == null || getClass() != o.getClass()) {
+      return false;
+    }
+
+    KeyInfo keyInfo = (KeyInfo) o;
+
+    return new EqualsBuilder()
+        .append(version, keyInfo.version)
+        .append(keyName, keyInfo.keyName)
+        .isEquals();
+  }
+
+  @Override
+  public int hashCode() {
+    return new HashCodeBuilder(17, 37)
+        .append(version)
+        .append(keyName)
+        .toHashCode();
+  }
+
+  /**
+
+   * Parse a string to retuen BucketInfo Object.
+   *
+   * @param jsonString - Json String
+   *
+   * @return - BucketInfo
+   *
+   * @throws IOException
+   */
+  public static KeyInfo parse(String jsonString) throws IOException {
+    ObjectMapper mapper = new ObjectMapper();
+    return mapper.readValue(jsonString, KeyInfo.class);
+  }
+
+
+  /**
+   * Returns a JSON string of this object.
+   * After stripping out bytesUsed and keyCount
+   *
+   * @return String
+   */
+  public String toJsonString() throws IOException {
+    String[] ignorableFieldNames = {"dataFileName"};
+
+    FilterProvider filters = new SimpleFilterProvider()
+        .addFilter(OBJECT_INFO, SimpleBeanPropertyFilter
+            .serializeAllExcept(ignorableFieldNames));
+
+    ObjectMapper mapper = new ObjectMapper()
+        .setVisibility(JsonMethod.FIELD, JsonAutoDetect.Visibility.ANY);
+    mapper.getSerializationConfig()
+        .addMixInAnnotations(Object.class, MixIn.class);
+    ObjectWriter writer = mapper.writer(filters);
+    return writer.writeValueAsString(this);
+  }
+
+  /**
+   * Returns the Object as a Json String.
+   */
+  public String toDBString() throws IOException {
+    ObjectMapper mapper = new ObjectMapper();
+    return mapper.writeValueAsString(this);
+  }
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/28f770d8/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/response/ListKeys.java
----------------------------------------------------------------------
diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/response/ListKeys.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/response/ListKeys.java
new file mode 100644
index 0000000..8b0d9cc
--- /dev/null
+++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/ozone/web/response/ListKeys.java
@@ -0,0 +1,183 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.hadoop.ozone.web.response;
+
+import org.apache.hadoop.ozone.web.handlers.ListArgs;
+import org.codehaus.jackson.annotate.JsonAutoDetect;
+import org.codehaus.jackson.annotate.JsonMethod;
+import org.codehaus.jackson.map.ObjectMapper;
+import org.codehaus.jackson.map.ObjectWriter;
+import org.codehaus.jackson.map.annotate.JsonFilter;
+import org.codehaus.jackson.map.ser.FilterProvider;
+import org.codehaus.jackson.map.ser.impl.SimpleBeanPropertyFilter;
+import org.codehaus.jackson.map.ser.impl.SimpleFilterProvider;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * This class the represents the list of keys (Objects) in a bucket.
+ */
+public class ListKeys {
+  static final String OBJECT_LIST = "OBJECT_LIST_FILTER";
+  private String name;
+  private String prefix;
+  private long maxKeys;
+  private boolean truncated;
+  private List<KeyInfo> objectList;
+
+  /**
+   * Default constructor needed for json serialization.
+   */
+  public ListKeys() {
+    this.objectList = new LinkedList<>();
+  }
+
+  /**
+   * Constructor for ListKeys.
+   *
+   * @param args      ListArgs
+   * @param truncated is truncated
+   */
+  public ListKeys(ListArgs args, boolean truncated) {
+    this.name = args.getBucketName();
+    this.prefix = args.getPrefix();
+    this.maxKeys = args.getMaxKeys();
+    this.truncated = truncated;
+  }
+
+  /**
+   * Converts a Json string to POJO.
+   * @param jsonString
+   * @return ListObject
+   * @throws IOException
+   */
+  public static ListKeys parse(String jsonString) throws IOException {
+    ObjectMapper mapper = new ObjectMapper();
+    return mapper.readValue(jsonString, ListKeys.class);
+  }
+
+  /**
+   * Returns a list of Objects.
+   *
+   * @return List of KeyInfo Objects.
+   */
+  public List<KeyInfo> getObjectList() {
+    return objectList;
+  }
+
+  /**
+   * Sets the list of Objects.
+   *
+   * @param objectList
+   */
+  public void setObjectList(List<KeyInfo> objectList) {
+    this.objectList = objectList;
+  }
+
+  /**
+   * Gets the Max Key Count.
+   *
+   * @return long
+   */
+  public long getMaxKeys() {
+    return maxKeys;
+  }
+
+  /**
+   * Gets bucket Name.
+   *
+   * @return String
+   */
+  public String getName() {
+    return name;
+  }
+
+  /**
+   * Gets Prefix.
+   *
+   * @return String
+   */
+  public String getPrefix() {
+    return prefix;
+  }
+
+  /**
+   * Gets truncated Status.
+   *
+   * @return Boolean
+   */
+  public boolean isTruncated() {
+    return truncated;
+  }
+
+  /**
+   * Sets the value of truncated.
+   *
+   * @param value - Boolean
+   */
+  public void setTruncated(boolean value) {
+    this.truncated = value;
+  }
+
+  /**
+   * Returns a JSON string of this object. After stripping out bytesUsed and
+   * keyCount.
+   *
+   * @return String
+   */
+  public String toJsonString() throws IOException {
+    String[] ignorableFieldNames = {"dataFileName"};
+
+    FilterProvider filters = new SimpleFilterProvider().addFilter(OBJECT_LIST,
+        SimpleBeanPropertyFilter.serializeAllExcept(ignorableFieldNames));
+
+    ObjectMapper mapper = new ObjectMapper()
+        .setVisibility(JsonMethod.FIELD, JsonAutoDetect.Visibility.ANY);
+    mapper.getSerializationConfig()
+        .addMixInAnnotations(Object.class, MixIn.class);
+    ObjectWriter writer = mapper.writer(filters);
+    return writer.writeValueAsString(this);
+  }
+
+  /**
+   * Returns the Object as a Json String.
+   */
+  public String toDBString() throws IOException {
+    ObjectMapper mapper = new ObjectMapper();
+    return mapper.writeValueAsString(this);
+  }
+
+  /**
+   * Sorts the keys based on name and version. This is useful when we return the
+   * list of keys.
+   */
+  public void sort() {
+    Collections.sort(objectList);
+  }
+
+  /**
+   * This class allows us to create custom filters for the Json serialization.
+   */
+  @JsonFilter(OBJECT_LIST)
+  class MixIn {
+
+  }
+}