@Override
 public S3Resource write(long length, InputStream in) throws ResourceException, IOException {
   // TODO V2 better errorhandling
   if ((null != s3Object) && (isDirectory()))
     throw new IllegalStateException(
         "This resource is already defined as directory. Can't write content to directory");
   // extract the header attributes and contentType
   Map<String, String> header = this.finalizeHeader();
   String ct = header.remove(S3Headers.CONTENT_TYPE);
   MimeType contentType = (null != ct) ? new MimeType(ct) : null;
   this.uri = encodeAsFile(this.uri);
   // put the S3 object
   try {
     S3Response response =
         S3Object.putObject(encodeAsFile(this.uri), header, contentType, length, in);
     S3Response delete = null;
     // delete old S3Object if URL has changed
     if ((null != this.s3Object) && (!this.s3Object.uri.equals(this.uri)))
       delete = S3Object.deleteObject(this.s3Object.uri);
     // init this resource instance
     if (null == s3Object) this.s3Object = new S3Object(response);
     else this.s3Object.updateByResponse(response);
     this.uri = this.s3Object.uri;
     this.modifiedHeader = null;
   } catch (S3Exception e) {
     if (e.getErrorCode() == HttpURLConnection.HTTP_NOT_FOUND)
       throw new FileNotFoundException("file not found" + e.toString());
     else throw new ResourceException("error while writing resource", e);
   }
   return this;
 }
 /**
  * Get the status of the S3 resource from S3(exists, isDirectory, isReadable, etc.
  *
  * <p>ATTENTION: this initiates a HEAD request to S3
  *
  * @throws ResourceException
  * @throws IOException
  */
 protected void getStatus() throws IOException, ResourceException {
   try {
     this.s3Object = S3Object.getHeadObject(this.uri, null);
     this.modifiedHeader = null;
   } catch (S3Exception e) {
     if (e.getErrorCode() == HttpURLConnection.HTTP_NOT_FOUND) {
       // object not found is not an exception for getStatus but an valid information
       this.s3Object = null;
     } else
       // everything else in en exception
       throw new ResourceException(e);
   }
 }
 @Override
 public OutputStream getOutputStream() throws IOException, ResourceException {
   if ((null != this.s3Object) && (!isFile(this.s3Object.uri)))
     throw new IllegalStateException("Cant getInputStream for directory resource");
   // check the resource status
   this.uri = encodeAsFile(this.uri);
   try {
     // if connection not already available fetch the object
     if ((null == this.s3Object) || (null == this.s3Object.getOutputStream())) {
       this.s3Object =
           S3Object.getObject(uri, (null != this.s3Object) ? this.s3Object.getVersionId() : null);
       this.uri = this.s3Object.uri;
       this.modifiedHeader = null;
     }
     return s3Object.getOutputStream();
   } catch (S3Exception e) {
     if (e.getErrorCode() == HttpURLConnection.HTTP_NOT_FOUND)
       throw new FileNotFoundException("file not found" + e.toString());
     else throw new ResourceException("error while getting resource", e);
   }
 }
 @Override
 public S3Resource createDirectoryResource() throws ResourceException, IOException {
   if (null != this.s3Object)
     if (!this.s3Object.isDeleted())
       throw new IllegalStateException(
           "Can't create new directory resource because it already exists");
   // extract the header attributes and contentType
   Map<String, String> header = this.finalizeHeader();
   // put the S3 object
   try {
     S3Response response = S3Object.putObject(encodeAsDirectory(this.uri), header, null, 0, null);
     // init this resource instance
     this.s3Object = new S3Object(response);
     this.uri = this.s3Object.uri;
     this.modifiedHeader = null;
   } catch (S3Exception e) {
     if (e.getErrorCode() == HttpURLConnection.HTTP_NOT_FOUND)
       throw new FileNotFoundException("file not found" + e.toString());
     else throw new ResourceException("error while creating resource", e);
   }
   return this;
 }
 /*
  * ############################################################
  * operations which alter the physical resource and persist changes
  * ############################################################
  */
 @Override
 public boolean delete() throws ResourceException, IOException {
   try {
     S3Response response = S3Object.deleteObject(this.uri);
     if (response.getReturnCode() != HttpURLConnection.HTTP_NO_CONTENT)
       throw new ResourceException(
           "something went wrong when deleting the file: " + response.toString());
     /*
      * At this moment we know the URI of the object and that it is deleted (isFile=FALSE). Therefore the resource
      * has to be reset, to behave like a new constructed one.
      * But under versioning it still exists but with new versionID and delete marker
      */
     this.s3Object = new S3Object(response);
     this.modifiedHeader = null;
     return true;
   } catch (S3Exception e) {
     if (e.getErrorCode() == HttpURLConnection.HTTP_NOT_FOUND) {
       logger.info("file not found" + e.toString());
       return false;
     } else throw new ResourceException("error while deleting", e);
   }
 }