You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ga...@apache.org on 2014/08/12 21:30:22 UTC

git commit: JCLOUDS-658: use xattr only on supported systems

Repository: jclouds
Updated Branches:
  refs/heads/master 95b6064c3 -> 9009bb526


JCLOUDS-658: use xattr only on supported systems

Mac OS X HFS+ does not support UserDefinedFileAttributeView:

https://bugs.openjdk.java.net/browse/JDK-8030048


Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/9009bb52
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/9009bb52
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/9009bb52

Branch: refs/heads/master
Commit: 9009bb526875aa25a60aedb1811ecdea439759b5
Parents: 95b6064
Author: Andrew Gaul <ga...@apache.org>
Authored: Mon Aug 11 15:34:41 2014 -0700
Committer: Andrew Gaul <ga...@apache.org>
Committed: Tue Aug 12 12:30:06 2014 -0700

----------------------------------------------------------------------
 .../internal/FilesystemStorageStrategyImpl.java | 115 +++++++++++--------
 .../FilesystemBlobIntegrationTest.java          |  38 ++++++
 .../FilesystemContainerIntegrationTest.java     |  15 +++
 .../test/java/org/jclouds/utils/TestUtils.java  |   5 +
 4 files changed, 124 insertions(+), 49 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/9009bb52/apis/filesystem/src/main/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImpl.java
----------------------------------------------------------------------
diff --git a/apis/filesystem/src/main/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImpl.java b/apis/filesystem/src/main/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImpl.java
index 74ebef7..ea975e8 100644
--- a/apis/filesystem/src/main/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImpl.java
+++ b/apis/filesystem/src/main/java/org/jclouds/filesystem/strategy/internal/FilesystemStorageStrategyImpl.java
@@ -16,6 +16,9 @@
  */
 package org.jclouds.filesystem.strategy.internal;
 
+import static java.nio.file.Files.getFileAttributeView;
+import static java.nio.file.Files.getFileStore;
+
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Strings.isNullOrEmpty;
 import static com.google.common.io.BaseEncoding.base16;
@@ -23,6 +26,7 @@ import static com.google.common.io.BaseEncoding.base16;
 import java.io.File;
 import java.io.IOException;
 import java.nio.ByteBuffer;
+import java.nio.file.Path;
 import java.nio.file.attribute.UserDefinedFileAttributeView;
 import java.nio.charset.StandardCharsets;
 import java.util.Date;
@@ -196,47 +200,58 @@ public class FilesystemStorageStrategyImpl implements LocalStorageStrategy {
       BlobBuilder builder = blobBuilders.get();
       builder.name(key);
       File file = getFileForBlobKey(container, key);
+      Path path = file.toPath();
       ByteSource byteSource = Files.asByteSource(file);
       try {
-         UserDefinedFileAttributeView view = java.nio.file.Files.getFileAttributeView(
-            file.toPath(), UserDefinedFileAttributeView.class);
-         Set<String> attributes = ImmutableSet.copyOf(view.list());
-
-         String contentDisposition = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_DISPOSITION);
-         String contentEncoding = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_ENCODING);
-         String contentLanguage = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_LANGUAGE);
-         String contentType = readStringAttributeIfPresent(view, attributes, XATTR_CONTENT_TYPE);
+         String contentDisposition = null;
+         String contentEncoding = null;
+         String contentLanguage = null;
+         String contentType = null;
          HashCode hashCode = null;
-         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());
-         }
          Date expires = null;
-         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());
-         }
          ImmutableMap.Builder<String, String> userMetadata = ImmutableMap.builder();
-         for (String attribute : attributes) {
-            if (!attribute.startsWith(XATTR_USER_METADATA_PREFIX)) {
-               continue;
+
+         if (getFileStore(file.toPath()).supportsFileAttributeView(UserDefinedFileAttributeView.class)) {
+            UserDefinedFileAttributeView view = getFileAttributeView(path, UserDefinedFileAttributeView.class);
+            Set<String> attributes = ImmutableSet.copyOf(view.list());
+
+            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 (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);
             }
-            String value = readStringAttributeIfPresent(view, attributes, attribute);
-            userMetadata.put(attribute.substring(XATTR_USER_METADATA_PREFIX.length()), value);
-         }
 
-         builder.payload(byteSource)
-            .contentDisposition(contentDisposition)
-            .contentEncoding(contentEncoding)
-            .contentLanguage(contentLanguage)
-            .contentLength(byteSource.size())
-            .contentMD5(hashCode)
-            .contentType(contentType)
-            .expires(expires)
-            .userMetadata(userMetadata.build());
+            builder.payload(byteSource)
+               .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);
       }
@@ -256,6 +271,7 @@ public class FilesystemStorageStrategyImpl implements LocalStorageStrategy {
       filesystemContainerNameValidator.validate(containerName);
       filesystemBlobKeyValidator.validate(blobKey);
       File outputFile = getFileForBlobKey(containerName, blobKey);
+      Path outputPath = outputFile.toPath();
       HashingInputStream his = null;
       try {
          Files.createParentDirs(outputFile);
@@ -269,21 +285,22 @@ public class FilesystemStorageStrategyImpl implements LocalStorageStrategy {
          }
          payload.getContentMetadata().setContentMD5(actualHashCode);
 
-         UserDefinedFileAttributeView view = java.nio.file.Files.getFileAttributeView(
-            outputFile.toPath(), UserDefinedFileAttributeView.class);
-         view.write(XATTR_CONTENT_MD5, ByteBuffer.wrap(actualHashCode.asBytes()));
-         writeStringAttributeIfPresent(view, XATTR_CONTENT_DISPOSITION, metadata.getContentDisposition());
-         writeStringAttributeIfPresent(view, XATTR_CONTENT_ENCODING, metadata.getContentEncoding());
-         writeStringAttributeIfPresent(view, XATTR_CONTENT_LANGUAGE, metadata.getContentLanguage());
-         writeStringAttributeIfPresent(view, XATTR_CONTENT_TYPE, metadata.getContentType());
-         Date expires = metadata.getExpires();
-         if (expires != null) {
-            ByteBuffer buf = ByteBuffer.allocate(Longs.BYTES).putLong(expires.getTime());
-            buf.flip();
-            view.write(XATTR_EXPIRES, buf);
-         }
-         for (Map.Entry<String, String> entry : blob.getMetadata().getUserMetadata().entrySet()) {
-            writeStringAttributeIfPresent(view, XATTR_USER_METADATA_PREFIX + entry.getKey(), entry.getValue());
+         if (getFileStore(outputPath).supportsFileAttributeView(UserDefinedFileAttributeView.class)) {
+            UserDefinedFileAttributeView view = getFileAttributeView(outputPath, UserDefinedFileAttributeView.class);
+            view.write(XATTR_CONTENT_MD5, ByteBuffer.wrap(actualHashCode.asBytes()));
+            writeStringAttributeIfPresent(view, XATTR_CONTENT_DISPOSITION, metadata.getContentDisposition());
+            writeStringAttributeIfPresent(view, XATTR_CONTENT_ENCODING, metadata.getContentEncoding());
+            writeStringAttributeIfPresent(view, XATTR_CONTENT_LANGUAGE, metadata.getContentLanguage());
+            writeStringAttributeIfPresent(view, XATTR_CONTENT_TYPE, metadata.getContentType());
+            Date expires = metadata.getExpires();
+            if (expires != null) {
+               ByteBuffer buf = ByteBuffer.allocate(Longs.BYTES).putLong(expires.getTime());
+               buf.flip();
+               view.write(XATTR_EXPIRES, buf);
+            }
+            for (Map.Entry<String, String> entry : blob.getMetadata().getUserMetadata().entrySet()) {
+               writeStringAttributeIfPresent(view, XATTR_USER_METADATA_PREFIX + entry.getKey(), entry.getValue());
+            }
          }
          return base16().lowerCase().encode(actualHashCode.asBytes());
       } catch (IOException ex) {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/9009bb52/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemBlobIntegrationTest.java
----------------------------------------------------------------------
diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemBlobIntegrationTest.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemBlobIntegrationTest.java
index 3618fd4..f5ca672 100644
--- a/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemBlobIntegrationTest.java
+++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemBlobIntegrationTest.java
@@ -16,8 +16,11 @@
  */
 package org.jclouds.filesystem.integration;
 
+import java.io.IOException;
 import java.util.Properties;
 
+import org.jclouds.blobstore.domain.Blob;
+import org.jclouds.blobstore.domain.BlobMetadata;
 import org.jclouds.blobstore.integration.internal.BaseBlobIntegrationTest;
 import org.jclouds.blobstore.integration.internal.BaseBlobStoreIntegrationTest;
 import org.jclouds.filesystem.reference.FilesystemConstants;
@@ -37,4 +40,39 @@ public class FilesystemBlobIntegrationTest extends BaseBlobIntegrationTest {
       props.setProperty(FilesystemConstants.PROPERTY_BASEDIR, TestUtils.TARGET_BASE_DIR);
       return props;
    }
+
+   // Mac OS X HFS+ does not support UserDefinedFileAttributeView:
+   // https://bugs.openjdk.java.net/browse/JDK-8030048
+   @Override
+   public void checkContentMetadata(Blob blob) {
+      if (!org.jclouds.utils.TestUtils.isMacOSX()) {
+         super.checkContentMetadata(blob);
+      }
+   }
+
+   // Mac OS X HFS+ does not support UserDefinedFileAttributeView:
+   // https://bugs.openjdk.java.net/browse/JDK-8030048
+   @Override
+   protected void checkContentDisposition(Blob blob, String contentDisposition) {
+      if (!org.jclouds.utils.TestUtils.isMacOSX()) {
+         super.checkContentDisposition(blob, contentDisposition);
+      }
+   }
+
+   // Mac OS X HFS+ does not support UserDefinedFileAttributeView:
+   // https://bugs.openjdk.java.net/browse/JDK-8030048
+   @Override
+   protected void validateMetadata(BlobMetadata metadata) throws IOException {
+      if (!org.jclouds.utils.TestUtils.isMacOSX()) {
+         super.validateMetadata(metadata);
+      }
+   }
+
+   // Mac OS X HFS+ does not support UserDefinedFileAttributeView:
+   // https://bugs.openjdk.java.net/browse/JDK-8030048
+   @Test(dataProvider = "ignoreOnMacOSX")
+   @Override
+   public void testCreateBlobWithExpiry() throws InterruptedException {
+      super.testCreateBlobWithExpiry();
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/9009bb52/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java
----------------------------------------------------------------------
diff --git a/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java b/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java
index d5a02a0..4b6cd03 100644
--- a/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java
+++ b/apis/filesystem/src/test/java/org/jclouds/filesystem/integration/FilesystemContainerIntegrationTest.java
@@ -19,6 +19,7 @@ package org.jclouds.filesystem.integration;
 import static org.jclouds.blobstore.options.ListContainerOptions.Builder.maxResults;
 import static org.testng.Assert.assertEquals;
 
+import java.io.IOException;
 import java.util.Properties;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.TimeoutException;
@@ -80,6 +81,14 @@ public class FilesystemContainerIntegrationTest extends BaseContainerIntegration
       }
    }
 
+   // Mac OS X HFS+ does not support UserDefinedFileAttributeView:
+   // https://bugs.openjdk.java.net/browse/JDK-8030048
+   @Test(dataProvider = "ignoreOnMacOSX")
+   @Override
+   public void testWithDetails() throws InterruptedException, IOException {
+      super.testWithDetails();
+   }
+
    @Override
    @Test(dataProvider = "ignoreOnWindows")
    public void containerExists() throws InterruptedException {
@@ -147,6 +156,12 @@ public class FilesystemContainerIntegrationTest extends BaseContainerIntegration
    }
 
    @DataProvider
+   public Object[][] ignoreOnMacOSX() {
+      return org.jclouds.utils.TestUtils.isMacOSX() ? TestUtils.NO_INVOCATIONS
+            : TestUtils.SINGLE_NO_ARG_INVOCATION;
+   }
+
+   @DataProvider
    public Object[][] ignoreOnWindows() {
       return TestUtils.isWindowsOs() ? TestUtils.NO_INVOCATIONS
             : TestUtils.SINGLE_NO_ARG_INVOCATION;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/9009bb52/core/src/test/java/org/jclouds/utils/TestUtils.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/jclouds/utils/TestUtils.java b/core/src/test/java/org/jclouds/utils/TestUtils.java
index b62fefd..e276103 100644
--- a/core/src/test/java/org/jclouds/utils/TestUtils.java
+++ b/core/src/test/java/org/jclouds/utils/TestUtils.java
@@ -29,6 +29,11 @@ public class TestUtils {
     public static final Object[][] NO_INVOCATIONS = new Object[0][0];
     public static final Object[][] SINGLE_NO_ARG_INVOCATION = { new Object[0] };
 
+    public static boolean isMacOSX() {
+        String osName = System.getProperty("os.name");
+        return osName.contains("OS X");
+    }
+
     public static ByteSource randomByteSource() {
         return randomByteSource(0);
     }