kopia lustrzana https://github.com/gaul/s3proxy
Add filesystem-nio2 blobstore
This uses the same code paths as transient-nio2 and will replace the jclouds filesystem blobstore.pull/719/head
rodzic
8f5a812c69
commit
7632e9cc3e
|
@ -77,6 +77,7 @@ Maven Central hosts S3Proxy artifacts and the wiki has
|
|||
* azureblob-sdk (newer but lacks multi-part upload, see [Azure/azure-sdk-for-java#42603](https://github.com/Azure/azure-sdk-for-java/issues/42603))
|
||||
* b2
|
||||
* filesystem (on-disk storage)
|
||||
* filesystem-nio2 (on-disk storage, preview)
|
||||
* google-cloud-storage
|
||||
* openstack-swift
|
||||
* rackspace-cloudfiles-uk and rackspace-cloudfiles-us
|
||||
|
|
|
@ -51,12 +51,9 @@ import com.google.common.hash.HashingInputStream;
|
|||
import com.google.common.io.BaseEncoding;
|
||||
import com.google.common.io.ByteSource;
|
||||
import com.google.common.io.ByteStreams;
|
||||
import com.google.common.jimfs.Configuration;
|
||||
import com.google.common.jimfs.Jimfs;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
import com.google.common.primitives.Longs;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
import jakarta.ws.rs.core.Response.Status;
|
||||
|
||||
|
@ -98,9 +95,9 @@ import org.slf4j.Logger;
|
|||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@Singleton
|
||||
public final class Nio2BlobStore extends BaseBlobStore {
|
||||
public abstract class AbstractNio2BlobStore extends BaseBlobStore {
|
||||
private static final Logger logger = LoggerFactory.getLogger(
|
||||
Nio2BlobStore.class);
|
||||
AbstractNio2BlobStore.class);
|
||||
private static final String XATTR_CACHE_CONTROL = "user.cache-control";
|
||||
private static final String XATTR_CONTENT_DISPOSITION =
|
||||
"user.content-disposition";
|
||||
|
@ -120,31 +117,29 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
|
||||
private final Supplier<Set<? extends Location>> locations;
|
||||
private final FileSystem fs;
|
||||
private final Path root;
|
||||
|
||||
@Inject
|
||||
Nio2BlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
protected AbstractNio2BlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations,
|
||||
PayloadSlicer slicer,
|
||||
@org.jclouds.location.Provider Supplier<Credentials> creds) {
|
||||
@org.jclouds.location.Provider Supplier<Credentials> creds,
|
||||
FileSystem fs, Path root) {
|
||||
super(context, blobUtils, defaultLocation, locations, slicer);
|
||||
this.locations = requireNonNull(locations, "locations");
|
||||
// TODO: close this
|
||||
this.fs = Jimfs.newFileSystem(Configuration.unix().toBuilder()
|
||||
.setAttributeViews("posix", "user")
|
||||
.setWorkingDirectory("/")
|
||||
.build());
|
||||
this.fs = fs;
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<? extends Location> listAssignableLocations() {
|
||||
public final Set<? extends Location> listAssignableLocations() {
|
||||
return locations.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageSet<? extends StorageMetadata> list() {
|
||||
public final PageSet<? extends StorageMetadata> list() {
|
||||
var set = ImmutableSortedSet.<StorageMetadata>naturalOrder();
|
||||
try (var stream = Files.newDirectoryStream(fs.getPath(""))) {
|
||||
try (var stream = Files.newDirectoryStream(root)) {
|
||||
for (var path : stream) {
|
||||
var attr = Files.readAttributes(path,
|
||||
BasicFileAttributes.class);
|
||||
|
@ -164,7 +159,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public PageSet<? extends StorageMetadata> list(String container,
|
||||
public final PageSet<? extends StorageMetadata> list(String container,
|
||||
ListContainerOptions options) {
|
||||
if (!containerExists(container)) {
|
||||
throw new ContainerNotFoundException(container, "");
|
||||
|
@ -178,7 +173,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
var prefix = options.getPrefix();
|
||||
var dirPrefix = fs.getPath(container);
|
||||
var dirPrefix = root.resolve(container);
|
||||
if (prefix != null) {
|
||||
int idx = prefix.lastIndexOf('/');
|
||||
if (idx != -1) {
|
||||
|
@ -292,22 +287,22 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean containerExists(String container) {
|
||||
return Files.exists(fs.getPath(container));
|
||||
public final boolean containerExists(String container) {
|
||||
return Files.exists(root.resolve(container));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createContainerInLocation(Location location,
|
||||
public final boolean createContainerInLocation(Location location,
|
||||
String container) {
|
||||
return createContainerInLocation(location, container,
|
||||
new CreateContainerOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean createContainerInLocation(Location location,
|
||||
public final boolean createContainerInLocation(Location location,
|
||||
String container, CreateContainerOptions options) {
|
||||
try {
|
||||
Files.createDirectory(fs.getPath(container));
|
||||
Files.createDirectory(root.resolve(container));
|
||||
} catch (FileAlreadyExistsException faee) {
|
||||
return false;
|
||||
} catch (IOException ioe) {
|
||||
|
@ -320,9 +315,9 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void deleteContainer(String container) {
|
||||
public final void deleteContainer(String container) {
|
||||
try {
|
||||
Files.deleteIfExists(fs.getPath(container));
|
||||
Files.deleteIfExists(root.resolve(container));
|
||||
} catch (DirectoryNotEmptyException dnee) {
|
||||
// TODO: what to do?
|
||||
} catch (IOException ioe) {
|
||||
|
@ -331,17 +326,17 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public boolean blobExists(String container, String key) {
|
||||
public final boolean blobExists(String container, String key) {
|
||||
return blobMetadata(container, key) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Blob getBlob(String container, String key, GetOptions options) {
|
||||
public final Blob getBlob(String container, String key, GetOptions options) {
|
||||
if (!containerExists(container)) {
|
||||
throw new ContainerNotFoundException(container, "");
|
||||
}
|
||||
|
||||
var path = fs.getPath(container, key);
|
||||
var path = root.resolve(container).resolve(key);
|
||||
logger.debug("Getting blob at: " + path);
|
||||
|
||||
try {
|
||||
|
@ -515,19 +510,19 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String putBlob(String container, Blob blob) {
|
||||
public final String putBlob(String container, Blob blob) {
|
||||
return putBlob(container, blob, new PutOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String putBlob(String container, Blob blob, PutOptions options) {
|
||||
public final String putBlob(String container, Blob blob, PutOptions options) {
|
||||
if (!containerExists(container)) {
|
||||
throw new ContainerNotFoundException(container, "");
|
||||
}
|
||||
|
||||
var path = fs.getPath(container, blob.getMetadata().getName());
|
||||
var path = root.resolve(container).resolve(blob.getMetadata().getName());
|
||||
// TODO: should we use a known suffix to filter these out during list?
|
||||
var tmpPath = fs.getPath(container, blob.getMetadata().getName() + "-" + UUID.randomUUID());
|
||||
var tmpPath = root.resolve(container).resolve(blob.getMetadata().getName() + "-" + UUID.randomUUID());
|
||||
logger.debug("Creating blob at: " + path);
|
||||
|
||||
if (blob.getMetadata().getName().endsWith("/")) {
|
||||
|
@ -606,7 +601,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String copyBlob(String fromContainer, String fromName,
|
||||
public final String copyBlob(String fromContainer, String fromName,
|
||||
String toContainer, String toName, CopyOptions options) {
|
||||
var blob = getBlob(fromContainer, fromName);
|
||||
if (blob == null) {
|
||||
|
@ -685,9 +680,9 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void removeBlob(String container, String key) {
|
||||
public final void removeBlob(String container, String key) {
|
||||
try {
|
||||
var path = fs.getPath(container, key);
|
||||
var path = root.resolve(container).resolve(key);
|
||||
Files.delete(path);
|
||||
removeEmptyParentDirectories(path.getParent());
|
||||
} catch (NoSuchFileException nsfe) {
|
||||
|
@ -698,7 +693,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public BlobMetadata blobMetadata(String container, String key) {
|
||||
public final BlobMetadata blobMetadata(String container, String key) {
|
||||
Blob blob = getBlob(container, key);
|
||||
if (blob == null) {
|
||||
return null;
|
||||
|
@ -713,18 +708,18 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected boolean deleteAndVerifyContainerGone(String container) {
|
||||
protected final boolean deleteAndVerifyContainerGone(String container) {
|
||||
deleteContainer(container);
|
||||
return !containerExists(container);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ContainerAccess getContainerAccess(String container) {
|
||||
public final ContainerAccess getContainerAccess(String container) {
|
||||
if (!containerExists(container)) {
|
||||
throw new ContainerNotFoundException(container, "");
|
||||
}
|
||||
|
||||
var path = fs.getPath(container);
|
||||
var path = root.resolve(container);
|
||||
Set<PosixFilePermission> permissions;
|
||||
try {
|
||||
permissions = Files.getPosixFilePermissions(path);
|
||||
|
@ -736,12 +731,12 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setContainerAccess(String container, ContainerAccess access) {
|
||||
public final void setContainerAccess(String container, ContainerAccess access) {
|
||||
if (!containerExists(container)) {
|
||||
throw new ContainerNotFoundException(container, "");
|
||||
}
|
||||
|
||||
var path = fs.getPath(container);
|
||||
var path = root.resolve(container);
|
||||
Set<PosixFilePermission> permissions;
|
||||
try {
|
||||
permissions = new HashSet<>(Files.getPosixFilePermissions(path));
|
||||
|
@ -757,7 +752,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public BlobAccess getBlobAccess(String container, String key) {
|
||||
public final BlobAccess getBlobAccess(String container, String key) {
|
||||
if (!containerExists(container)) {
|
||||
throw new ContainerNotFoundException(container, "");
|
||||
}
|
||||
|
@ -765,7 +760,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
throw new KeyNotFoundException(container, key, "");
|
||||
}
|
||||
|
||||
var path = fs.getPath(container, key);
|
||||
var path = root.resolve(container).resolve(key);
|
||||
Set<PosixFilePermission> permissions;
|
||||
try {
|
||||
permissions = Files.getPosixFilePermissions(path);
|
||||
|
@ -777,7 +772,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setBlobAccess(String container, String key, BlobAccess access) {
|
||||
public final void setBlobAccess(String container, String key, BlobAccess access) {
|
||||
if (!containerExists(container)) {
|
||||
throw new ContainerNotFoundException(container, "");
|
||||
}
|
||||
|
@ -785,7 +780,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
throw new KeyNotFoundException(container, key, "");
|
||||
}
|
||||
|
||||
var path = fs.getPath(container, key);
|
||||
var path = root.resolve(container).resolve(key);
|
||||
Set<PosixFilePermission> permissions;
|
||||
try {
|
||||
permissions = new HashSet<>(Files.getPosixFilePermissions(path));
|
||||
|
@ -801,7 +796,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public MultipartUpload initiateMultipartUpload(String container,
|
||||
public final MultipartUpload initiateMultipartUpload(String container,
|
||||
BlobMetadata blobMetadata, PutOptions options) {
|
||||
var uploadId = UUID.randomUUID().toString();
|
||||
// create a stub blob
|
||||
|
@ -812,7 +807,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void abortMultipartUpload(MultipartUpload mpu) {
|
||||
public final void abortMultipartUpload(MultipartUpload mpu) {
|
||||
var parts = listMultipartUpload(mpu);
|
||||
for (var part : parts) {
|
||||
removeBlob(mpu.containerName(), MULTIPART_PREFIX + mpu.id() + "-" + mpu.blobName() + "-" + part.partNumber());
|
||||
|
@ -821,7 +816,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String completeMultipartUpload(MultipartUpload mpu, List<MultipartPart> parts) {
|
||||
public final String completeMultipartUpload(MultipartUpload mpu, List<MultipartPart> parts) {
|
||||
var metas = ImmutableList.<BlobMetadata>builder();
|
||||
long contentLength = 0;
|
||||
var md5Hasher = Hashing.md5().newHasher();
|
||||
|
@ -893,7 +888,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public MultipartPart uploadMultipartPart(MultipartUpload mpu, int partNumber, Payload payload) {
|
||||
public final MultipartPart uploadMultipartPart(MultipartUpload mpu, int partNumber, Payload payload) {
|
||||
var partName = MULTIPART_PREFIX + mpu.id() + "-" + mpu.blobName() + "-" + partNumber;
|
||||
var blob = blobBuilder(partName)
|
||||
.payload(payload)
|
||||
|
@ -905,7 +900,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<MultipartPart> listMultipartUpload(MultipartUpload mpu) {
|
||||
public final List<MultipartPart> listMultipartUpload(MultipartUpload mpu) {
|
||||
var parts = ImmutableList.<MultipartPart>builder();
|
||||
var options =
|
||||
new ListContainerOptions().prefix(MULTIPART_PREFIX + mpu.id() + "-" + mpu.blobName() + "-").recursive();
|
||||
|
@ -928,7 +923,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<MultipartUpload> listMultipartUploads(String container) {
|
||||
public final List<MultipartUpload> listMultipartUploads(String container) {
|
||||
var mpus = ImmutableList.<MultipartUpload>builder();
|
||||
var options = new ListContainerOptions().prefix(MULTIPART_PREFIX).recursive();
|
||||
int uuidLength = UUID.randomUUID().toString().length();
|
||||
|
@ -955,22 +950,22 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
@Override
|
||||
public long getMinimumMultipartPartSize() {
|
||||
public final long getMinimumMultipartPartSize() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaximumMultipartPartSize() {
|
||||
public final long getMaximumMultipartPartSize() {
|
||||
return 100 * 1024 * 1024;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumNumberOfParts() {
|
||||
public final int getMaximumNumberOfParts() {
|
||||
return 50 * 1000;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream streamBlob(String container, String name) {
|
||||
public final InputStream streamBlob(String container, String name) {
|
||||
throw new UnsupportedOperationException("not yet implemented");
|
||||
}
|
||||
|
||||
|
@ -1073,7 +1068,7 @@ public final class Nio2BlobStore extends BaseBlobStore {
|
|||
}
|
||||
|
||||
/**
|
||||
* Nio2BlobStore implicitly creates directories when creating a key /a/b/c.
|
||||
* AbstractNio2BlobStore implicitly creates directories when creating a key /a/b/c.
|
||||
* When removing /a/b/c, it must clean up /a and /a/b, unless a client explicitly created a subdirectory which has file attributes.
|
||||
*/
|
||||
private static void removeEmptyParentDirectories(Path path) throws IOException {
|
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* Copyright 2014-2024 Andrew Gaul <andrew@gaul.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.gaul.s3proxy.nio2blob;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.reflect.Reflection2;
|
||||
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
||||
|
||||
public final class FilesystemNio2BlobApiMetadata extends BaseHttpApiMetadata {
|
||||
public FilesystemNio2BlobApiMetadata() {
|
||||
this(builder());
|
||||
}
|
||||
|
||||
protected FilesystemNio2BlobApiMetadata(Builder builder) {
|
||||
super(builder);
|
||||
}
|
||||
|
||||
private static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return builder().fromApiMetadata(this);
|
||||
}
|
||||
|
||||
public static Properties defaultProperties() {
|
||||
return BaseHttpApiMetadata.defaultProperties();
|
||||
}
|
||||
|
||||
// Fake API client
|
||||
private interface FilesystemNio2BlobClient {
|
||||
}
|
||||
|
||||
public static final class Builder
|
||||
extends BaseHttpApiMetadata.Builder<FilesystemNio2BlobClient, Builder> {
|
||||
protected Builder() {
|
||||
super(FilesystemNio2BlobClient.class);
|
||||
id("filesystem-nio2")
|
||||
.name("Filesystem NIO.2 Blobstore")
|
||||
.identityName("Account Name")
|
||||
.credentialName("Access Key")
|
||||
.defaultEndpoint("http://localhost/")
|
||||
.documentation(URI.create(
|
||||
"http://www.jclouds.org/documentation/userguide" +
|
||||
"/blobstore-guide"))
|
||||
.defaultProperties(FilesystemNio2BlobApiMetadata.defaultProperties())
|
||||
.view(Reflection2.typeToken(BlobStoreContext.class))
|
||||
.defaultModules(Set.of(FilesystemNio2BlobStoreContextModule.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public FilesystemNio2BlobApiMetadata build() {
|
||||
return new FilesystemNio2BlobApiMetadata(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Builder self() {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -27,12 +27,12 @@ import org.jclouds.providers.internal.BaseProviderMetadata;
|
|||
* Implementation of org.jclouds.types.ProviderMetadata for NIO.2 filesystems.
|
||||
*/
|
||||
@AutoService(ProviderMetadata.class)
|
||||
public final class Nio2BlobProviderMetadata extends BaseProviderMetadata {
|
||||
public Nio2BlobProviderMetadata() {
|
||||
public final class FilesystemNio2BlobProviderMetadata extends BaseProviderMetadata {
|
||||
public FilesystemNio2BlobProviderMetadata() {
|
||||
super(builder());
|
||||
}
|
||||
|
||||
public Nio2BlobProviderMetadata(Builder builder) {
|
||||
public FilesystemNio2BlobProviderMetadata(Builder builder) {
|
||||
super(builder);
|
||||
}
|
||||
|
||||
|
@ -52,17 +52,17 @@ public final class Nio2BlobProviderMetadata extends BaseProviderMetadata {
|
|||
}
|
||||
public static final class Builder extends BaseProviderMetadata.Builder {
|
||||
protected Builder() {
|
||||
id("transient-nio2")
|
||||
id("filesystem-nio2")
|
||||
.name("NIO.2 filesystem blobstore")
|
||||
.apiMetadata(new Nio2BlobApiMetadata())
|
||||
.apiMetadata(new FilesystemNio2BlobApiMetadata())
|
||||
.endpoint("https://127.0.0.1") // TODO:
|
||||
.defaultProperties(
|
||||
Nio2BlobProviderMetadata.defaultProperties());
|
||||
FilesystemNio2BlobProviderMetadata.defaultProperties());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nio2BlobProviderMetadata build() {
|
||||
return new Nio2BlobProviderMetadata(this);
|
||||
public FilesystemNio2BlobProviderMetadata build() {
|
||||
return new FilesystemNio2BlobProviderMetadata(this);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 2014-2024 Andrew Gaul <andrew@gaul.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.gaul.s3proxy.nio2blob;
|
||||
|
||||
import java.nio.file.FileSystem;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.filesystem.reference.FilesystemConstants;
|
||||
import org.jclouds.io.PayloadSlicer;
|
||||
|
||||
@Singleton
|
||||
public final class FilesystemNio2BlobStore extends AbstractNio2BlobStore {
|
||||
@Inject
|
||||
FilesystemNio2BlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations,
|
||||
PayloadSlicer slicer,
|
||||
@org.jclouds.location.Provider Supplier<Credentials> creds,
|
||||
@Named(FilesystemConstants.PROPERTY_BASEDIR) String baseDir) {
|
||||
this(context, blobUtils, defaultLocation, locations, slicer, creds,
|
||||
baseDir, FileSystems.getDefault());
|
||||
}
|
||||
|
||||
// Helper to create Path
|
||||
private FilesystemNio2BlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations,
|
||||
PayloadSlicer slicer,
|
||||
@org.jclouds.location.Provider Supplier<Credentials> creds,
|
||||
@Named(FilesystemConstants.PROPERTY_BASEDIR) String baseDir,
|
||||
FileSystem fs) {
|
||||
super(context, blobUtils, defaultLocation, locations, slicer, creds,
|
||||
fs, fs.getPath(baseDir));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2014-2024 Andrew Gaul <andrew@gaul.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.gaul.s3proxy.nio2blob;
|
||||
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Scopes;
|
||||
|
||||
import org.jclouds.blobstore.BlobStore;
|
||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||
|
||||
public final class FilesystemNio2BlobStoreContextModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
|
||||
bind(BlobStore.class).to(FilesystemNio2BlobStore.class).in(Scopes.SINGLETON);
|
||||
}
|
||||
}
|
|
@ -24,12 +24,12 @@ import org.jclouds.blobstore.BlobStoreContext;
|
|||
import org.jclouds.reflect.Reflection2;
|
||||
import org.jclouds.rest.internal.BaseHttpApiMetadata;
|
||||
|
||||
public final class Nio2BlobApiMetadata extends BaseHttpApiMetadata {
|
||||
public Nio2BlobApiMetadata() {
|
||||
public final class TransientNio2BlobApiMetadata extends BaseHttpApiMetadata {
|
||||
public TransientNio2BlobApiMetadata() {
|
||||
this(builder());
|
||||
}
|
||||
|
||||
protected Nio2BlobApiMetadata(Builder builder) {
|
||||
protected TransientNio2BlobApiMetadata(Builder builder) {
|
||||
super(builder);
|
||||
}
|
||||
|
||||
|
@ -47,29 +47,29 @@ public final class Nio2BlobApiMetadata extends BaseHttpApiMetadata {
|
|||
}
|
||||
|
||||
// Fake API client
|
||||
private interface Nio2BlobClient {
|
||||
private interface TransientNio2BlobClient {
|
||||
}
|
||||
|
||||
public static final class Builder
|
||||
extends BaseHttpApiMetadata.Builder<Nio2BlobClient, Builder> {
|
||||
extends BaseHttpApiMetadata.Builder<TransientNio2BlobClient, Builder> {
|
||||
protected Builder() {
|
||||
super(Nio2BlobClient.class);
|
||||
super(TransientNio2BlobClient.class);
|
||||
id("transient-nio2")
|
||||
.name("NIO.2 Blobstore")
|
||||
.name("Transient NIO.2 Blobstore")
|
||||
.identityName("Account Name")
|
||||
.credentialName("Access Key")
|
||||
.defaultEndpoint("http://localhost/")
|
||||
.documentation(URI.create(
|
||||
"http://www.jclouds.org/documentation/userguide" +
|
||||
"/blobstore-guide"))
|
||||
.defaultProperties(Nio2BlobApiMetadata.defaultProperties())
|
||||
.defaultProperties(TransientNio2BlobApiMetadata.defaultProperties())
|
||||
.view(Reflection2.typeToken(BlobStoreContext.class))
|
||||
.defaultModules(Set.of(Nio2BlobStoreContextModule.class));
|
||||
.defaultModules(Set.of(TransientNio2BlobStoreContextModule.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Nio2BlobApiMetadata build() {
|
||||
return new Nio2BlobApiMetadata(this);
|
||||
public TransientNio2BlobApiMetadata build() {
|
||||
return new TransientNio2BlobApiMetadata(this);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* Copyright 2014-2024 Andrew Gaul <andrew@gaul.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.gaul.s3proxy.nio2blob;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import com.google.auto.service.AutoService;
|
||||
|
||||
import org.jclouds.providers.ProviderMetadata;
|
||||
import org.jclouds.providers.internal.BaseProviderMetadata;
|
||||
|
||||
/**
|
||||
* Implementation of org.jclouds.types.ProviderMetadata for NIO.2 filesystems.
|
||||
*/
|
||||
@AutoService(ProviderMetadata.class)
|
||||
public final class TransientNio2BlobProviderMetadata extends BaseProviderMetadata {
|
||||
public TransientNio2BlobProviderMetadata() {
|
||||
super(builder());
|
||||
}
|
||||
|
||||
public TransientNio2BlobProviderMetadata(Builder builder) {
|
||||
super(builder);
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder toBuilder() {
|
||||
return builder().fromProviderMetadata(this);
|
||||
}
|
||||
|
||||
public static Properties defaultProperties() {
|
||||
Properties properties = new Properties();
|
||||
// TODO: filesystem basedir
|
||||
return properties;
|
||||
}
|
||||
public static final class Builder extends BaseProviderMetadata.Builder {
|
||||
protected Builder() {
|
||||
id("transient-nio2")
|
||||
.name("Filesystem NIO.2 blobstore")
|
||||
.apiMetadata(new TransientNio2BlobApiMetadata())
|
||||
.endpoint("https://127.0.0.1") // TODO:
|
||||
.defaultProperties(
|
||||
TransientNio2BlobProviderMetadata.defaultProperties());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TransientNio2BlobProviderMetadata build() {
|
||||
return new TransientNio2BlobProviderMetadata(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Builder fromProviderMetadata(
|
||||
ProviderMetadata in) {
|
||||
super.fromProviderMetadata(in);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Copyright 2014-2024 Andrew Gaul <andrew@gaul.org>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.gaul.s3proxy.nio2blob;
|
||||
|
||||
import java.nio.file.FileSystem;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.jimfs.Configuration;
|
||||
import com.google.common.jimfs.Jimfs;
|
||||
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Singleton;
|
||||
|
||||
import org.jclouds.blobstore.BlobStoreContext;
|
||||
import org.jclouds.blobstore.util.BlobUtils;
|
||||
import org.jclouds.collect.Memoized;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.domain.Location;
|
||||
import org.jclouds.io.PayloadSlicer;
|
||||
|
||||
@Singleton
|
||||
public final class TransientNio2BlobStore extends AbstractNio2BlobStore {
|
||||
@Inject
|
||||
TransientNio2BlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations,
|
||||
PayloadSlicer slicer,
|
||||
@org.jclouds.location.Provider Supplier<Credentials> creds) {
|
||||
this(context, blobUtils, defaultLocation, locations, slicer, creds,
|
||||
Jimfs.newFileSystem(Configuration.unix().toBuilder()
|
||||
.setAttributeViews("posix", "user")
|
||||
.setWorkingDirectory("/")
|
||||
.build()));
|
||||
}
|
||||
|
||||
// Helper to create Path
|
||||
private TransientNio2BlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||
Supplier<Location> defaultLocation,
|
||||
@Memoized Supplier<Set<? extends Location>> locations,
|
||||
PayloadSlicer slicer,
|
||||
@org.jclouds.location.Provider Supplier<Credentials> creds,
|
||||
FileSystem fs) {
|
||||
super(context, blobUtils, defaultLocation, locations, slicer, creds,
|
||||
fs, fs.getPath(""));
|
||||
}
|
||||
}
|
|
@ -22,10 +22,10 @@ import com.google.inject.Scopes;
|
|||
import org.jclouds.blobstore.BlobStore;
|
||||
import org.jclouds.blobstore.attr.ConsistencyModel;
|
||||
|
||||
public final class Nio2BlobStoreContextModule extends AbstractModule {
|
||||
public final class TransientNio2BlobStoreContextModule extends AbstractModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT);
|
||||
bind(BlobStore.class).to(Nio2BlobStore.class).in(Scopes.SINGLETON);
|
||||
bind(BlobStore.class).to(TransientNio2BlobStore.class).in(Scopes.SINGLETON);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
s3proxy.endpoint=http://127.0.0.1:0
|
||||
s3proxy.secure-endpoint=https://127.0.0.1:0
|
||||
#s3proxy.service-path=s3proxy
|
||||
# authorization must be aws-v2, aws-v4, aws-v2-or-v4, or none
|
||||
s3proxy.authorization=aws-v2-or-v4
|
||||
s3proxy.identity=local-identity
|
||||
s3proxy.credential=local-credential
|
||||
s3proxy.keystore-path=keystore.jks
|
||||
s3proxy.keystore-password=password
|
||||
|
||||
jclouds.provider=filesystem-nio2
|
||||
jclouds.identity=remote-identity
|
||||
jclouds.credential=remote-credential
|
||||
# endpoint is optional for some providers
|
||||
#jclouds.endpoint=http://127.0.0.1:8081
|
||||
jclouds.filesystem.basedir=/tmp/blobstore
|
Ładowanie…
Reference in New Issue