@Override public void removeBlob(final String container, final String blobKey) { filesystemContainerNameValidator.validate(container); filesystemBlobKeyValidator.validate(blobKey); String fileName = buildPathStartingFromBaseDir(container, blobKey); logger.debug("Deleting blob %s", fileName); File fileToBeDeleted = new File(fileName); if (fileToBeDeleted.isDirectory()) { try { UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(fileToBeDeleted.toPath()); if (view != null) { for (String s : view.list()) { view.delete(s); } } } catch (IOException e) { logger.debug("Could not delete attributes from %s: %s", fileToBeDeleted, e); } } try { delete(fileToBeDeleted); } catch (IOException e) { logger.debug("Could not delete %s: %s", fileToBeDeleted, e); } // now examine if the key of the blob is a complex key (with a directory structure) // and eventually remove empty directory removeDirectoriesTreeOfBlobKey(container, blobKey); }
private boolean buildPathAndChecksIfBlobExists(String... tokens) throws IOException { String path = buildPathStartingFromBaseDir(tokens); File file = new File(path); boolean exists = file.exists() && file.isFile(); if (!exists && getDirectoryBlobSuffix(tokens[tokens.length - 1]) != null && file.isDirectory()) { UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(file.toPath()); exists = view != null && view.list().contains(XATTR_CONTENT_MD5); } return exists; }
static Map<String, ByteBuffer> readUserDefinedFileAttributes(Path file) throws IOException { UserDefinedFileAttributeView view = getFileAttributeView(file, UserDefinedFileAttributeView.class); Map<String, ByteBuffer> result = new HashMap<>(); for (String name : view.list()) { int size = view.size(name); ByteBuffer bb = ByteBuffer.allocate(size); int n = view.read(name, bb); assertTrue(n == size); bb.flip(); result.put(name, bb); } return result; }
public static long getFileKey(Path filePath) { if (!Files.exists(filePath)) { return -1; } try { if (OSDetector.isApple()) { Xattrj xattrj = getXattrj(); if (xattrj == null) { return -1; } String fileKey = xattrj.readAttribute(filePath.toFile(), "fileKey"); if (fileKey == null) { return -1; } return Long.parseLong(fileKey); } else { UserDefinedFileAttributeView userDefinedFileAttributeView = Files.getFileAttributeView(filePath, UserDefinedFileAttributeView.class); List<String> list = userDefinedFileAttributeView.list(); if (!list.contains("fileKey")) { return -1; } ByteBuffer byteBuffer = ByteBuffer.allocate(userDefinedFileAttributeView.size("fileKey")); userDefinedFileAttributeView.read("fileKey", byteBuffer); CharBuffer charBuffer = _CHARSET.decode((ByteBuffer) byteBuffer.flip()); return Long.parseLong(charBuffer.toString()); } } catch (Exception e) { _logger.error(e.getMessage(), e); return -1; } }
/** * Removes recursively the directory structure of a complex blob key, only if the directory is * empty * * @param container * @param blobKey */ private void removeDirectoriesTreeOfBlobKey(String container, String blobKey) { String normalizedBlobKey = denormalize(blobKey); // exists is no path is present in the blobkey if (!normalizedBlobKey.contains(File.separator)) return; File file = new File(normalizedBlobKey); // TODO // "/media/data/works/java/amazon/jclouds/master/filesystem/aa/bb/cc/dd/eef6f0c8-0206-460b-8870-352e6019893c.txt" String parentPath = file.getParent(); // no need to manage "/" parentPath, because "/" cannot be used as start // char of blobkey if (!isNullOrEmpty(parentPath)) { // remove parent directory only it's empty File directory = new File(buildPathStartingFromBaseDir(container, parentPath)); // don't delete directory if it's a directory blob try { UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(directory.toPath()); if (view == null) { // OSX HFS+ does not support UserDefinedFileAttributeView logger.debug("Could not look for attributes from %s", directory); } else if (!view.list().isEmpty()) { return; } } catch (IOException e) { logger.debug("Could not look for attributes from %s: %s", directory, e); } String[] children = directory.list(); if (null == children || children.length == 0) { try { delete(directory); } catch (IOException e) { logger.debug("Could not delete %s: %s", directory, e); return; } // recursively call for removing other path removeDirectoriesTreeOfBlobKey(container, parentPath); } } }
public static String getFileKey(Path filePath) { if (!Files.exists(filePath)) { return ""; } try { if (OSDetector.isWindows()) { UserDefinedFileAttributeView userDefinedFileAttributeView = Files.getFileAttributeView(filePath, UserDefinedFileAttributeView.class); List<String> list = userDefinedFileAttributeView.list(); if (!list.contains("fileKey")) { return ""; } ByteBuffer byteBuffer = ByteBuffer.allocate(userDefinedFileAttributeView.size("fileKey")); userDefinedFileAttributeView.read("fileKey", byteBuffer); CharBuffer charBuffer = _CHARSET.decode((ByteBuffer) byteBuffer.flip()); return charBuffer.toString(); } else { BasicFileAttributes basicFileAttributes = Files.readAttributes(filePath, BasicFileAttributes.class); Object fileKey = basicFileAttributes.fileKey(); return fileKey.toString(); } } catch (Exception e) { _logger.error(e.getMessage(), e); return ""; } }
@Override public Blob getBlob(final String container, final String key) { BlobBuilder builder = blobBuilders.get(); builder.name(key); File file = getFileForBlobKey(container, key); ByteSource byteSource; if (getDirectoryBlobSuffix(key) != null) { logger.debug("%s - %s is a directory", container, key); byteSource = ByteSource.empty(); } else { byteSource = Files.asByteSource(file); } try { String cacheControl = null; String contentDisposition = null; String contentEncoding = null; String contentLanguage = null; String contentType = null; HashCode hashCode = null; Date expires = null; ImmutableMap.Builder<String, String> userMetadata = ImmutableMap.builder(); UserDefinedFileAttributeView view = getUserDefinedFileAttributeView(file.toPath()); if (view != null) { Set<String> attributes = ImmutableSet.copyOf(view.list()); cacheControl = readStringAttributeIfPresent(view, attributes, XATTR_CACHE_CONTROL); contentDisposition = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_DISPOSITION); contentEncoding = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_ENCODING); contentLanguage = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_LANGUAGE); contentType = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_TYPE); if (contentType == null && autoDetectContentType) { contentType = probeContentType(file.toPath()); } if (attributes.contains(XATTR_CONTENT_MD5)) { ByteBuffer buf = ByteBuffer.allocate(view.size(XATTR_CONTENT_MD5)); view.read(XATTR_CONTENT_MD5, buf); hashCode = HashCode.fromBytes(buf.array()); } if (attributes.contains(XATTR_EXPIRES)) { ByteBuffer buf = ByteBuffer.allocate(view.size(XATTR_EXPIRES)); view.read(XATTR_EXPIRES, buf); buf.flip(); expires = new Date(buf.asLongBuffer().get()); } for (String attribute : attributes) { if (!attribute.startsWith(XATTR_USER_METADATA_PREFIX)) { continue; } String value = readStringAttributeIfPresent(view, attributes, attribute); userMetadata.put(attribute.substring(XATTR_USER_METADATA_PREFIX.length()), value); } builder .payload(byteSource) .cacheControl(cacheControl) .contentDisposition(contentDisposition) .contentEncoding(contentEncoding) .contentLanguage(contentLanguage) .contentLength(byteSource.size()) .contentMD5(hashCode) .contentType(contentType) .expires(expires) .userMetadata(userMetadata.build()); } else { builder .payload(byteSource) .contentLength(byteSource.size()) .contentMD5(byteSource.hash(Hashing.md5()).asBytes()); } } catch (IOException e) { throw Throwables.propagate(e); } Blob blob = builder.build(); blob.getMetadata().setContainer(container); blob.getMetadata().setLastModified(new Date(file.lastModified())); blob.getMetadata().setSize(file.length()); if (blob.getPayload().getContentMetadata().getContentMD5() != null) blob.getMetadata() .setETag( base16().lowerCase().encode(blob.getPayload().getContentMetadata().getContentMD5())); return blob; }