mirror of https://github.com/apache/jclouds.git
JCLOUDS-658: use xattr only on supported systems
Mac OS X HFS+ does not support UserDefinedFileAttributeView: https://bugs.openjdk.java.net/browse/JDK-8030048
This commit is contained in:
parent
95b6064c3d
commit
9009bb5268
|
@ -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;
|
||||
}
|
||||
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());
|
||||
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);
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
@ -146,6 +155,12 @@ public class FilesystemContainerIntegrationTest extends BaseContainerIntegration
|
|||
super.testListContainerMaxResults();
|
||||
}
|
||||
|
||||
@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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue