@Override
  public String writeStreamToStore(InputStream in, long actualSize, Mailbox mbox)
      throws IOException, ServiceException {
    MessageDigest digest;
    try {
      digest = MessageDigest.getInstance("SHA-256");
    } catch (NoSuchAlgorithmException e) {
      throw ServiceException.FAILURE("SHA-256 digest not found", e);
    }
    ByteUtil.PositionInputStream pin =
        new ByteUtil.PositionInputStream(new DigestInputStream(in, digest));

    HttpClient client = ZimbraHttpConnectionManager.getInternalHttpConnMgr().newHttpClient();
    PostMethod post = new PostMethod(getPostUrl(mbox));
    try {
      HttpClientUtil.addInputStreamToHttpMethod(post, pin, actualSize, "application/octet-stream");
      int statusCode = HttpClientUtil.executeMethod(client, post);
      if (statusCode == HttpStatus.SC_OK
          || statusCode == HttpStatus.SC_CREATED
          || statusCode == HttpStatus.SC_NO_CONTENT) {
        return getLocator(
            post, ByteUtil.encodeFSSafeBase64(digest.digest()), pin.getPosition(), mbox);
      } else {
        throw ServiceException.FAILURE("error POSTing blob: " + post.getStatusText(), null);
      }
    } finally {
      post.releaseConnection();
    }
  }
 @Override
 public InputStream readStreamFromStore(String locator, Mailbox mbox) throws IOException {
   HttpClient client = ZimbraHttpConnectionManager.getInternalHttpConnMgr().newHttpClient();
   GetMethod get = new GetMethod(getGetUrl(mbox, locator));
   int statusCode = HttpClientUtil.executeMethod(client, get);
   if (statusCode == HttpStatus.SC_OK) {
     return new UserServlet.HttpInputStream(get);
   } else {
     get.releaseConnection();
     throw new IOException("unexpected return code during blob GET: " + get.getStatusText());
   }
 }
 @Override
 public boolean deleteFromStore(String locator, Mailbox mbox) throws IOException {
   HttpClient client = ZimbraHttpConnectionManager.getInternalHttpConnMgr().newHttpClient();
   DeleteMethod delete = new DeleteMethod(getDeleteUrl(mbox, locator));
   try {
     int statusCode = HttpClientUtil.executeMethod(client, delete);
     if (statusCode == HttpStatus.SC_OK || statusCode == HttpStatus.SC_NO_CONTENT) {
       return true;
     } else if (statusCode == HttpStatus.SC_NOT_FOUND) {
       return false;
     } else {
       throw new IOException(
           "unexpected return code during blob DELETE: " + delete.getStatusText());
     }
   } finally {
     delete.releaseConnection();
   }
 }