Skip to content

Commit

Permalink
Fix getObjectMetadata issue for folders containing no metadata
Browse files Browse the repository at this point in the history
- manually handle the root folder FileObject creation
- when the candidate folder does not have metadata, try to call
  listObjects to see if the folder exists.
  • Loading branch information
fviale committed Oct 6, 2016
1 parent f6c1a33 commit 20c810d
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 15 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1 +1 @@
projectVersion=2.4.4
projectVersion=2.4.7
80 changes: 66 additions & 14 deletions src/main/java/com/github/vfss3/S3FileObject.java
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,18 @@ public S3FileObject(AbstractFileName fileName,

@Override
protected void doAttach() {

if (!attached) {
String candidateKey = getS3Key();
if ("".equals(candidateKey)) {
mimicFolderExistence(candidateKey, null);
logger.info("Attach root folder to S3 Object [" + objectKey + "]");
attached = true;
return;
}

try {
// Do we have file with name?
String candidateKey = getS3Key();
objectMetadata = getService().getObjectMetadata(getBucket().getName(), candidateKey);
objectKey = candidateKey;

Expand All @@ -110,10 +118,9 @@ protected void doAttach() {
catch (AmazonClientException e) {
// We are attempting to attach to the root bucket
}

try {
// Do we have folder with that name?
String candidateKey = getS3Key() + FileName.SEPARATOR;
candidateKey = getS3Key() + FileName.SEPARATOR;
objectMetadata = getService().getObjectMetadata(getBucket().getName(), candidateKey);
objectKey = candidateKey;
logger.info("Attach folder to S3 Object [" + objectKey + "]");
Expand All @@ -124,6 +131,25 @@ protected void doAttach() {
// No, we don't
}

try {
// check if the folder exists but has no metadata
candidateKey = getS3Key();
final ListObjectsRequest loReq = new ListObjectsRequest();
loReq.setBucketName(getBucket().getName());
loReq.setDelimiter("/");
loReq.setPrefix(candidateKey);
loReq.setMaxKeys(1);
ObjectListing listing = getService().listObjects(loReq);
if (listing.getCommonPrefixes().contains(candidateKey + FileName.SEPARATOR)) {
mimicFolderExistence(candidateKey + FileName.SEPARATOR, null);
logger.info("Attach folder with no metadata to S3 Object [" + objectKey + "]");
attached = true;
return;
}
} catch (AmazonClientException e) {
// the folder really does not exist
}

// Create a new
if (objectMetadata == null) {
objectMetadata = new ObjectMetadata();
Expand All @@ -138,6 +164,19 @@ protected void doAttach() {
}
}

private void mimicFolderExistence(String candidateKey, Date date) {
objectMetadata = new ObjectMetadata();
objectMetadata.setContentLength(0);
if (getServerSideEncryption()) {
objectMetadata.setSSEAlgorithm(AES_256_SERVER_SIDE_ENCRYPTION);
}
if (date != null) {
objectMetadata.setLastModified(date);
}
objectMetadata.setContentType(MIMETYPE_JETS3T_DIRECTORY);
objectKey = candidateKey;
}

@Override
protected void doDetach() throws Exception {
if (attached) {
Expand Down Expand Up @@ -232,15 +271,13 @@ protected FileType doGetType() throws Exception {
@Override
protected String[] doListChildren() throws Exception {
String path = objectKey;
// make sure we add a '/' slash at the end to find children
if ((!"".equals(path)) && (!path.endsWith(SEPARATOR))) {
path = path + "/";
}

path = getPathWithTrailingSlash(path);

final ListObjectsRequest loReq = new ListObjectsRequest();
loReq.setBucketName(getBucket().getName());
loReq.setDelimiter("/");
loReq.setPrefix(path);
loReq.setPrefix(getPathForListObjects(path));

ObjectListing listing = getService().listObjects(loReq);
final List<S3ObjectSummary> summaries = new ArrayList<S3ObjectSummary>(listing.getObjectSummaries());
Expand All @@ -255,6 +292,7 @@ protected String[] doListChildren() throws Exception {

// add the prefixes (non-empty subdirs) first
for (String commonPrefix : commonPrefixes) {

// strip path from name (leave only base name)
final String stripPath = commonPrefix.substring(path.length());
childrenNames.add(stripPath);
Expand Down Expand Up @@ -286,18 +324,17 @@ protected FileObject[] doListChildrenResolved() throws Exception
{
String path = objectKey;
// make sure we add a '/' slash at the end to find children
if ((!"".equals(path)) && (!path.endsWith(SEPARATOR))) {
path = path + "/";
}
path = getPathWithTrailingSlash(path);

final ListObjectsRequest loReq = new ListObjectsRequest();
loReq.setBucketName(getBucket().getName());
loReq.setDelimiter("/");
loReq.setPrefix(path);
loReq.setPrefix(getPathForListObjects(path));

ObjectListing listing = getService().listObjects(loReq);
final List<S3ObjectSummary> summaries = new ArrayList<S3ObjectSummary>(listing.getObjectSummaries());
final Set<String> commonPrefixes = new TreeSet<String>(listing.getCommonPrefixes());

while (listing.isTruncated()) {
listing = getService().listNextBatchOfObjects(listing);
summaries.addAll(listing.getObjectSummaries());
Expand All @@ -308,6 +345,7 @@ protected FileObject[] doListChildrenResolved() throws Exception

// add the prefixes (non-empty subdirs) first
for (String commonPrefix : commonPrefixes) {

// strip path from name (leave only base name)
String stripPath = commonPrefix.substring(path.length());
FileObject childObject = resolveFile(stripPath, (stripPath.equals("/")) ? FILE_SYSTEM : CHILD);
Expand Down Expand Up @@ -341,6 +379,20 @@ protected FileObject[] doListChildrenResolved() throws Exception
return resolvedChildren.toArray(new FileObject[resolvedChildren.size()]);
}

private String getPathWithTrailingSlash(String path) {
if (!"".equals(path) && !path.endsWith(SEPARATOR)) {
return path + "/";
}
return path;
}

private String getPathForListObjects(String path) {
if ("".equals(path)) {
return null;
}
return path;
}

@Override
protected long doGetContentSize() throws Exception {
return objectMetadata.getContentLength();
Expand Down Expand Up @@ -452,8 +504,8 @@ private String getS3Key() {
private String getS3Key(FileName fileName) {
String path = fileName.getPath();

if ("".equals(path)) {
return path;
if ("".equals(path) || ".".equals(path) || "/".equals(path)) {
return "";
} else {
return path.substring(1);
}
Expand Down

0 comments on commit 20c810d

Please sign in to comment.