@Test public void testPutIncorrectContentLength() throws Exception { Blob blob = new BlobBuilderImpl() .name("key") .payload(randomByteSource().slice(0, 1024)) .contentLength(512) .build(); try { storageStrategy.putBlob(CONTAINER_NAME, blob); Fail.failBecauseExceptionWasNotThrown(IOException.class); } catch (IOException ioe) { } }
@Override public String putBlob(final String containerName, final Blob blob) throws IOException { String blobKey = blob.getMetadata().getName(); Payload payload = blob.getPayload(); filesystemContainerNameValidator.validate(containerName); filesystemBlobKeyValidator.validate(blobKey); if (getDirectoryBlobSuffix(blobKey) != null) { return putDirectoryBlob(containerName, blob); } File outputFile = getFileForBlobKey(containerName, blobKey); String tmpBlobName = blobKey + "-" + UUID.randomUUID(); File tmpFile = getFileForBlobKey(containerName, tmpBlobName); Path tmpPath = tmpFile.toPath(); boolean isMpu = false; if (blob.getMetadata() != null && blob.getMetadata().getETag() != null) isMpu = MPU_ETAG_FORMAT.matcher(blob.getMetadata().getETag()).matches(); InputStream inputStream = null; byte[] eTag = null; try { Files.createParentDirs(tmpFile); if (isMpu) { inputStream = payload.openStream(); eTag = blob.getMetadata().getETag().getBytes(); } else { inputStream = new HashingInputStream(Hashing.md5(), payload.openStream()); } long actualSize = Files.asByteSink(tmpFile).writeFrom(inputStream); Long expectedSize = blob.getMetadata().getContentMetadata().getContentLength(); if (expectedSize != null && actualSize != expectedSize) { throw new IOException("Content-Length mismatch, actual: " + actualSize + " expected: " + expectedSize); } if (!isMpu) { HashCode actualHashCode = ((HashingInputStream) inputStream).hash(); HashCode expectedHashCode = payload.getContentMetadata().getContentMD5AsHashCode(); if (expectedHashCode != null && !actualHashCode.equals(expectedHashCode)) { throw new IOException("MD5 hash code mismatch, actual: " + actualHashCode + " expected: " + expectedHashCode); } payload.getContentMetadata().setContentMD5(actualHashCode); eTag = actualHashCode.asBytes(); } if (outputFile.exists()) { delete(outputFile); } UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(tmpPath); if (view != null) { try { view.write(XATTR_CONTENT_MD5, ByteBuffer.wrap(eTag)); writeCommonMetadataAttr(view, blob); } catch (IOException e) { logger.debug("xattrs not supported on %s", tmpPath); } } setBlobAccess(containerName, tmpBlobName, BlobAccess.PRIVATE); if (!tmpFile.renameTo(outputFile)) { throw new IOException("Could not rename file " + tmpFile + " to " + outputFile); } tmpFile = null; return base16().lowerCase().encode(eTag); } finally { if (tmpFile != null) { try { delete(tmpFile); } catch (IOException e) { logger.debug("Could not delete %s: %s", tmpFile, e); } } closeQuietly(inputStream); if (payload != null) { payload.release(); } } }
FilesystemStorageStrategyImpl implements LocalStorageStrategy { @Override public String putBlob(final String containerName, final Blob blob) throws IOException { String blobKey = blob.getMetadata().getName(); Payload payload = blob.getPayload(); filesystemContainerNameValidator.validate(containerName); filesystemBlobKeyValidator.validate(blobKey); if (getDirectoryBlobSuffix(blobKey) != null) { return putDirectoryBlob(containerName, blob); } File outputFile = getFileForBlobKey(containerName, blobKey); String tmpBlobName = blobKey + "-" + UUID.randomUUID(); File tmpFile = getFileForBlobKey(containerName, tmpBlobName); Path tmpPath = tmpFile.toPath(); boolean isMpu = false; if (blob.getMetadata() != null && blob.getMetadata().getETag() != null) isMpu = MPU_ETAG_FORMAT.matcher(blob.getMetadata().getETag()).matches(); InputStream inputStream = null; byte[] eTag = null; try { Files.createParentDirs(tmpFile); if (isMpu) { inputStream = payload.openStream(); eTag = blob.getMetadata().getETag().getBytes(); } else { inputStream = new HashingInputStream(Hashing.md5(), payload.openStream()); } long actualSize = Files.asByteSink(tmpFile).writeFrom(inputStream); Long expectedSize = blob.getMetadata().getContentMetadata().getContentLength(); if (expectedSize != null && actualSize != expectedSize) { throw new IOException("Content-Length mismatch, actual: " + actualSize + " expected: " + expectedSize); } if (!isMpu) { HashCode actualHashCode = ((HashingInputStream) inputStream).hash(); HashCode expectedHashCode = payload.getContentMetadata().getContentMD5AsHashCode(); if (expectedHashCode != null && !actualHashCode.equals(expectedHashCode)) { throw new IOException("MD5 hash code mismatch, actual: " + actualHashCode + " expected: " + expectedHashCode); } payload.getContentMetadata().setContentMD5(actualHashCode); eTag = actualHashCode.asBytes(); } if (outputFile.exists()) { delete(outputFile); } UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(tmpPath); if (view != null) { try { view.write(XATTR_CONTENT_MD5, ByteBuffer.wrap(eTag)); writeCommonMetadataAttr(view, blob); } catch (IOException e) { logger.debug("xattrs not supported on %s", tmpPath); } } setBlobAccess(containerName, tmpBlobName, BlobAccess.PRIVATE); if (!tmpFile.renameTo(outputFile)) { throw new IOException("Could not rename file " + tmpFile + " to " + outputFile); } tmpFile = null; return base16().lowerCase().encode(eTag); } finally { if (tmpFile != null) { try { delete(tmpFile); } catch (IOException e) { logger.debug("Could not delete %s: %s", tmpFile, e); } } closeQuietly(inputStream); if (payload != null) { payload.release(); } } } }
FilesystemStorageStrategyImpl implements LocalStorageStrategy { @Override public String putBlob(final String containerName, final Blob blob) throws IOException { String blobKey = blob.getMetadata().getName(); Payload payload = blob.getPayload(); filesystemContainerNameValidator.validate(containerName); filesystemBlobKeyValidator.validate(blobKey); if (getDirectoryBlobSuffix(blobKey) != null) { return putDirectoryBlob(containerName, blob); } File outputFile = getFileForBlobKey(containerName, blobKey); String tmpBlobName = blobKey + "-" + UUID.randomUUID(); File tmpFile = getFileForBlobKey(containerName, tmpBlobName); Path tmpPath = tmpFile.toPath(); boolean isMpu = false; if (blob.getMetadata() != null && blob.getMetadata().getETag() != null) isMpu = MPU_ETAG_FORMAT.matcher(blob.getMetadata().getETag()).matches(); InputStream inputStream = null; byte[] eTag = null; try { Files.createParentDirs(tmpFile); if (isMpu) { inputStream = payload.openStream(); eTag = blob.getMetadata().getETag().getBytes(); } else { inputStream = new HashingInputStream(Hashing.md5(), payload.openStream()); } long actualSize = Files.asByteSink(tmpFile).writeFrom(inputStream); Long expectedSize = blob.getMetadata().getContentMetadata().getContentLength(); if (expectedSize != null && actualSize != expectedSize) { throw new IOException("Content-Length mismatch, actual: " + actualSize + " expected: " + expectedSize); } if (!isMpu) { HashCode actualHashCode = ((HashingInputStream) inputStream).hash(); HashCode expectedHashCode = payload.getContentMetadata().getContentMD5AsHashCode(); if (expectedHashCode != null && !actualHashCode.equals(expectedHashCode)) { throw new IOException("MD5 hash code mismatch, actual: " + actualHashCode + " expected: " + expectedHashCode); } payload.getContentMetadata().setContentMD5(actualHashCode); eTag = actualHashCode.asBytes(); } if (outputFile.exists()) { delete(outputFile); } UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(tmpPath); if (view != null) { try { view.write(XATTR_CONTENT_MD5, ByteBuffer.wrap(eTag)); writeCommonMetadataAttr(view, blob); } catch (IOException e) { logger.debug("xattrs not supported on %s", tmpPath); } } setBlobAccess(containerName, tmpBlobName, BlobAccess.PRIVATE); if (!tmpFile.renameTo(outputFile)) { throw new IOException("Could not rename file " + tmpFile + " to " + outputFile); } tmpFile = null; return base16().lowerCase().encode(eTag); } finally { if (tmpFile != null) { try { delete(tmpFile); } catch (IOException e) { logger.debug("Could not delete %s: %s", tmpFile, e); } } closeQuietly(inputStream); if (payload != null) { payload.release(); } } } @Inject protected  FilesystemStorageStrategyImpl(Provider<BlobBuilder> blobBuilders,
         @Named(FilesystemConstants.PROPERTY_BASEDIR) String baseDir,
         @Named(FilesystemConstants.PROPERTY_AUTO_DETECT_CONTENT_TYPE) boolean autoDetectContentType,
         FilesystemContainerNameValidator filesystemContainerNameValidator,
         FilesystemBlobKeyValidator filesystemBlobKeyValidator,
         Supplier<Location> defaultLocation); }
FilesystemStorageStrategyImpl implements LocalStorageStrategy { @Override public String putBlob(final String containerName, final Blob blob) throws IOException { String blobKey = blob.getMetadata().getName(); Payload payload = blob.getPayload(); filesystemContainerNameValidator.validate(containerName); filesystemBlobKeyValidator.validate(blobKey); if (getDirectoryBlobSuffix(blobKey) != null) { return putDirectoryBlob(containerName, blob); } File outputFile = getFileForBlobKey(containerName, blobKey); String tmpBlobName = blobKey + "-" + UUID.randomUUID(); File tmpFile = getFileForBlobKey(containerName, tmpBlobName); Path tmpPath = tmpFile.toPath(); boolean isMpu = false; if (blob.getMetadata() != null && blob.getMetadata().getETag() != null) isMpu = MPU_ETAG_FORMAT.matcher(blob.getMetadata().getETag()).matches(); InputStream inputStream = null; byte[] eTag = null; try { Files.createParentDirs(tmpFile); if (isMpu) { inputStream = payload.openStream(); eTag = blob.getMetadata().getETag().getBytes(); } else { inputStream = new HashingInputStream(Hashing.md5(), payload.openStream()); } long actualSize = Files.asByteSink(tmpFile).writeFrom(inputStream); Long expectedSize = blob.getMetadata().getContentMetadata().getContentLength(); if (expectedSize != null && actualSize != expectedSize) { throw new IOException("Content-Length mismatch, actual: " + actualSize + " expected: " + expectedSize); } if (!isMpu) { HashCode actualHashCode = ((HashingInputStream) inputStream).hash(); HashCode expectedHashCode = payload.getContentMetadata().getContentMD5AsHashCode(); if (expectedHashCode != null && !actualHashCode.equals(expectedHashCode)) { throw new IOException("MD5 hash code mismatch, actual: " + actualHashCode + " expected: " + expectedHashCode); } payload.getContentMetadata().setContentMD5(actualHashCode); eTag = actualHashCode.asBytes(); } if (outputFile.exists()) { delete(outputFile); } UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(tmpPath); if (view != null) { try { view.write(XATTR_CONTENT_MD5, ByteBuffer.wrap(eTag)); writeCommonMetadataAttr(view, blob); } catch (IOException e) { logger.debug("xattrs not supported on %s", tmpPath); } } setBlobAccess(containerName, tmpBlobName, BlobAccess.PRIVATE); if (!tmpFile.renameTo(outputFile)) { throw new IOException("Could not rename file " + tmpFile + " to " + outputFile); } tmpFile = null; return base16().lowerCase().encode(eTag); } finally { if (tmpFile != null) { try { delete(tmpFile); } catch (IOException e) { logger.debug("Could not delete %s: %s", tmpFile, e); } } closeQuietly(inputStream); if (payload != null) { payload.release(); } } } @Inject protected  FilesystemStorageStrategyImpl(Provider<BlobBuilder> blobBuilders,
         @Named(FilesystemConstants.PROPERTY_BASEDIR) String baseDir,
         @Named(FilesystemConstants.PROPERTY_AUTO_DETECT_CONTENT_TYPE) boolean autoDetectContentType,
         FilesystemContainerNameValidator filesystemContainerNameValidator,
         FilesystemBlobKeyValidator filesystemBlobKeyValidator,
         Supplier<Location> defaultLocation); @Override boolean containerExists(String container); @Override Collection<String> getAllContainerNames(); @Override boolean createContainerInLocation(String container, Location location, CreateContainerOptions options); @Override ContainerAccess getContainerAccess(String container); @Override void setContainerAccess(String container, ContainerAccess access); @Override void deleteContainer(String container); @Override void clearContainer(final String container); @Override void clearContainer(String container, ListContainerOptions options); @Override StorageMetadata getContainerMetadata(String container); @Override boolean blobExists(String container, String key); @Override Iterable<String> getBlobKeysInsideContainer(String container, String prefix); @Override Blob getBlob(final String container, final String key); @Override String putBlob(final String containerName, final Blob blob); @Override void removeBlob(final String container, final String blobKey); @Override BlobAccess getBlobAccess(String containerName, String blobName); @Override void setBlobAccess(String container, String name, BlobAccess access); @Override Location getLocation(final String containerName); @Override String getSeparator(); boolean createContainer(String container); Blob newBlob(@ParamValidators({ FilesystemBlobKeyValidator.class }) String name); File getFileForBlobKey(String container, String blobKey); boolean directoryExists(String container, String directory); void createDirectory(String container, String directory); void deleteDirectory(String container, String directory); long countBlobs(String container, ListContainerOptions options); }
FilesystemStorageStrategyImpl implements LocalStorageStrategy { @Override public String putBlob(final String containerName, final Blob blob) throws IOException { String blobKey = blob.getMetadata().getName(); Payload payload = blob.getPayload(); filesystemContainerNameValidator.validate(containerName); filesystemBlobKeyValidator.validate(blobKey); if (getDirectoryBlobSuffix(blobKey) != null) { return putDirectoryBlob(containerName, blob); } File outputFile = getFileForBlobKey(containerName, blobKey); String tmpBlobName = blobKey + "-" + UUID.randomUUID(); File tmpFile = getFileForBlobKey(containerName, tmpBlobName); Path tmpPath = tmpFile.toPath(); boolean isMpu = false; if (blob.getMetadata() != null && blob.getMetadata().getETag() != null) isMpu = MPU_ETAG_FORMAT.matcher(blob.getMetadata().getETag()).matches(); InputStream inputStream = null; byte[] eTag = null; try { Files.createParentDirs(tmpFile); if (isMpu) { inputStream = payload.openStream(); eTag = blob.getMetadata().getETag().getBytes(); } else { inputStream = new HashingInputStream(Hashing.md5(), payload.openStream()); } long actualSize = Files.asByteSink(tmpFile).writeFrom(inputStream); Long expectedSize = blob.getMetadata().getContentMetadata().getContentLength(); if (expectedSize != null && actualSize != expectedSize) { throw new IOException("Content-Length mismatch, actual: " + actualSize + " expected: " + expectedSize); } if (!isMpu) { HashCode actualHashCode = ((HashingInputStream) inputStream).hash(); HashCode expectedHashCode = payload.getContentMetadata().getContentMD5AsHashCode(); if (expectedHashCode != null && !actualHashCode.equals(expectedHashCode)) { throw new IOException("MD5 hash code mismatch, actual: " + actualHashCode + " expected: " + expectedHashCode); } payload.getContentMetadata().setContentMD5(actualHashCode); eTag = actualHashCode.asBytes(); } if (outputFile.exists()) { delete(outputFile); } UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(tmpPath); if (view != null) { try { view.write(XATTR_CONTENT_MD5, ByteBuffer.wrap(eTag)); writeCommonMetadataAttr(view, blob); } catch (IOException e) { logger.debug("xattrs not supported on %s", tmpPath); } } setBlobAccess(containerName, tmpBlobName, BlobAccess.PRIVATE); if (!tmpFile.renameTo(outputFile)) { throw new IOException("Could not rename file " + tmpFile + " to " + outputFile); } tmpFile = null; return base16().lowerCase().encode(eTag); } finally { if (tmpFile != null) { try { delete(tmpFile); } catch (IOException e) { logger.debug("Could not delete %s: %s", tmpFile, e); } } closeQuietly(inputStream); if (payload != null) { payload.release(); } } } @Inject protected  FilesystemStorageStrategyImpl(Provider<BlobBuilder> blobBuilders,
         @Named(FilesystemConstants.PROPERTY_BASEDIR) String baseDir,
         @Named(FilesystemConstants.PROPERTY_AUTO_DETECT_CONTENT_TYPE) boolean autoDetectContentType,
         FilesystemContainerNameValidator filesystemContainerNameValidator,
         FilesystemBlobKeyValidator filesystemBlobKeyValidator,
         Supplier<Location> defaultLocation); @Override boolean containerExists(String container); @Override Collection<String> getAllContainerNames(); @Override boolean createContainerInLocation(String container, Location location, CreateContainerOptions options); @Override ContainerAccess getContainerAccess(String container); @Override void setContainerAccess(String container, ContainerAccess access); @Override void deleteContainer(String container); @Override void clearContainer(final String container); @Override void clearContainer(String container, ListContainerOptions options); @Override StorageMetadata getContainerMetadata(String container); @Override boolean blobExists(String container, String key); @Override Iterable<String> getBlobKeysInsideContainer(String container, String prefix); @Override Blob getBlob(final String container, final String key); @Override String putBlob(final String containerName, final Blob blob); @Override void removeBlob(final String container, final String blobKey); @Override BlobAccess getBlobAccess(String containerName, String blobName); @Override void setBlobAccess(String container, String name, BlobAccess access); @Override Location getLocation(final String containerName); @Override String getSeparator(); boolean createContainer(String container); Blob newBlob(@ParamValidators({ FilesystemBlobKeyValidator.class }) String name); File getFileForBlobKey(String container, String blobKey); boolean directoryExists(String container, String directory); void createDirectory(String container, String directory); void deleteDirectory(String container, String directory); long countBlobs(String container, ListContainerOptions options);  }