|
|
|
package com.fanruan.fs.s3.repository.core;
|
|
|
|
|
|
|
|
import com.amazonaws.auth.AWSStaticCredentialsProvider;
|
|
|
|
import com.amazonaws.auth.BasicAWSCredentials;
|
|
|
|
import com.amazonaws.client.builder.AwsClientBuilder;
|
|
|
|
import com.amazonaws.services.s3.AmazonS3;
|
|
|
|
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
|
|
|
|
import com.amazonaws.services.s3.model.CopyObjectRequest;
|
|
|
|
import com.amazonaws.services.s3.model.DeleteObjectRequest;
|
|
|
|
import com.amazonaws.services.s3.model.GetObjectRequest;
|
|
|
|
import com.amazonaws.services.s3.model.ListObjectsRequest;
|
|
|
|
import com.amazonaws.services.s3.model.ObjectListing;
|
|
|
|
import com.amazonaws.services.s3.model.ObjectMetadata;
|
|
|
|
import com.amazonaws.services.s3.model.PutObjectRequest;
|
|
|
|
import com.amazonaws.services.s3.model.S3Object;
|
|
|
|
import com.amazonaws.services.s3.model.S3ObjectSummary;
|
|
|
|
import com.fanruan.api.log.LogKit;
|
|
|
|
import com.fanruan.api.util.StringKit;
|
|
|
|
import com.fr.io.repository.FineFileEntry;
|
|
|
|
import com.fr.io.repository.base.BaseResourceRepository;
|
|
|
|
import com.fr.stable.Filter;
|
|
|
|
import com.fr.workspace.resource.ResourceIOException;
|
|
|
|
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
|
|
import java.io.InputStream;
|
|
|
|
import java.net.URL;
|
|
|
|
import java.net.URLConnection;
|
|
|
|
import java.util.ArrayList;
|
|
|
|
import java.util.List;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @author richie
|
|
|
|
* @version 10.0
|
|
|
|
* Created by richie on 2020/6/15
|
|
|
|
*/
|
|
|
|
public class S3ResourceRepository extends BaseResourceRepository {
|
|
|
|
|
|
|
|
private static final String DELIMITER = "/";
|
|
|
|
|
|
|
|
private final AmazonS3 s3;
|
|
|
|
private final String bucket;
|
|
|
|
|
|
|
|
|
|
|
|
public S3ResourceRepository(String repoName, String workRoot, S3Config config) {
|
|
|
|
super(repoName, workRoot);
|
|
|
|
BasicAWSCredentials credentials = new BasicAWSCredentials(config.getAccessKeyId(), config.getAccessKeySecret());
|
|
|
|
this.s3 = AmazonS3ClientBuilder.standard()
|
|
|
|
.withEndpointConfiguration(new AwsClientBuilder.EndpointConfiguration(config.getEndPoint(), config.getRegion()))
|
|
|
|
.withCredentials(new AWSStaticCredentialsProvider(credentials)).build();
|
|
|
|
this.bucket = config.getBucket();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String getSeparator() {
|
|
|
|
return "/";
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public FineFileEntry getEntry(String path) {
|
|
|
|
GetObjectRequest request = new GetObjectRequest(bucket, path);
|
|
|
|
S3Object s3Object = s3.getObject(request);
|
|
|
|
return s3Object2FileEntry(s3Object, path);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public FineFileEntry[] listEntry(String dir) {
|
|
|
|
List<FineFileEntry> result = new ArrayList<>();
|
|
|
|
if (!dir.endsWith(DELIMITER)) {
|
|
|
|
dir += DELIMITER;
|
|
|
|
}
|
|
|
|
ListObjectsRequest listObjectsRequest = new ListObjectsRequest().withBucketName(bucket)
|
|
|
|
.withPrefix(dir).withDelimiter(DELIMITER);
|
|
|
|
ObjectListing objectListing = s3.listObjects(listObjectsRequest);
|
|
|
|
for (S3ObjectSummary summary : objectListing.getObjectSummaries()) {
|
|
|
|
String key = summary.getKey();
|
|
|
|
if (!key.endsWith(DELIMITER)) {
|
|
|
|
result.add(s3Object2FileEntry(summary, key));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (String prefix : objectListing.getCommonPrefixes()) {
|
|
|
|
FineFileEntry entry = new FineFileEntry(prefix);
|
|
|
|
entry.setDirectory(true);
|
|
|
|
result.add(entry);
|
|
|
|
}
|
|
|
|
|
|
|
|
return result.toArray(new FineFileEntry[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
private FineFileEntry s3Object2FileEntry(S3ObjectSummary s3Object, String path) {
|
|
|
|
FineFileEntry entry = new FineFileEntry(path);
|
|
|
|
entry.setDirectory(s3Object.getKey().endsWith("/"));
|
|
|
|
entry.setSize(s3Object.getSize());
|
|
|
|
entry.setTimestamp(s3Object.getLastModified().getTime());
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
private FineFileEntry s3Object2FileEntry(S3Object s3Object, String path) {
|
|
|
|
FineFileEntry entry = new FineFileEntry(path);
|
|
|
|
entry.setDirectory(s3Object.getKey().endsWith("/"));
|
|
|
|
entry.setSize(s3Object.getObjectMetadata().getContentLength());
|
|
|
|
entry.setTimestamp(s3Object.getObjectMetadata().getLastModified().getTime());
|
|
|
|
return entry;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public URL getResource(String path) {
|
|
|
|
throw new RuntimeException("Not support method.");
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public InputStream read(String filePath) throws ResourceIOException {
|
|
|
|
GetObjectRequest request = new GetObjectRequest(bucket, filePath);
|
|
|
|
try {
|
|
|
|
return s3.getObject(request).getObjectContent();
|
|
|
|
} catch (Exception e) {
|
|
|
|
return new ByteArrayInputStream(new byte[0]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void write(String path, byte[] data) {
|
|
|
|
ObjectMetadata metadata;
|
|
|
|
try {
|
|
|
|
metadata = s3.getObjectMetadata(bucket, path);
|
|
|
|
} catch (Exception e) {
|
|
|
|
metadata = new ObjectMetadata();
|
|
|
|
String mimeType = URLConnection.guessContentTypeFromName(path);
|
|
|
|
if (mimeType != null) {
|
|
|
|
metadata.setContentType(mimeType);
|
|
|
|
}
|
|
|
|
metadata.setContentLength(data.length);
|
|
|
|
}
|
|
|
|
s3.putObject(bucket, path, new ByteArrayInputStream(data), metadata);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean createFile(String path) {
|
|
|
|
PutObjectRequest request = new PutObjectRequest(bucket, path, new ByteArrayInputStream(new byte[0]), new ObjectMetadata());
|
|
|
|
try {
|
|
|
|
s3.putObject(request);
|
|
|
|
} catch (Exception e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean createDirectory(String path) {
|
|
|
|
PutObjectRequest request = new PutObjectRequest(bucket, path + "/", new ByteArrayInputStream(new byte[0]), new ObjectMetadata());
|
|
|
|
try {
|
|
|
|
s3.putObject(request);
|
|
|
|
} catch (Exception e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean delete(String path) {
|
|
|
|
try {
|
|
|
|
s3.deleteObject(bucket, path);
|
|
|
|
} catch (Exception e) {
|
|
|
|
LogKit.error(e.getMessage(), e);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean exist(String path) {
|
|
|
|
try {
|
|
|
|
return !s3.listObjects(bucket, path).getObjectSummaries().isEmpty();
|
|
|
|
} catch (Exception e) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String[] list(String dir, final Filter<String> filter) {
|
|
|
|
List<String> result = new ArrayList<>();
|
|
|
|
if (!dir.endsWith(DELIMITER)) {
|
|
|
|
dir += DELIMITER;
|
|
|
|
}
|
|
|
|
ListObjectsRequest listObjectsRequest = new ListObjectsRequest().withBucketName(bucket)
|
|
|
|
.withPrefix(dir).withDelimiter(DELIMITER);
|
|
|
|
ObjectListing objectListing = s3.listObjects(listObjectsRequest);
|
|
|
|
for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
|
|
|
|
String[] arr = objectSummary.getKey().split(DELIMITER);
|
|
|
|
String name = arr[arr.length - 1];
|
|
|
|
if (filter == null) {
|
|
|
|
result.add(name);
|
|
|
|
} else {
|
|
|
|
if (filter.accept(name)) {
|
|
|
|
result.add(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (String prefix : objectListing.getCommonPrefixes()) {
|
|
|
|
String[] arr = prefix.split(DELIMITER);
|
|
|
|
String name = arr[arr.length - 1] + DELIMITER;
|
|
|
|
if (filter == null) {
|
|
|
|
result.add(name);
|
|
|
|
} else {
|
|
|
|
if (filter.accept(name)) {
|
|
|
|
result.add(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return result.toArray(new String[0]);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean isDirectory(String path) {
|
|
|
|
if (path.endsWith(DELIMITER)) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
ObjectListing listing = s3.listObjects(bucket, path);
|
|
|
|
if (listing.getObjectSummaries().isEmpty()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
if (listing.getObjectSummaries().size() > 1) {
|
|
|
|
return true;
|
|
|
|
} else {
|
|
|
|
S3ObjectSummary summary = listing.getObjectSummaries().get(0);
|
|
|
|
return !StringKit.equals(listing.getPrefix(), summary.getKey());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public long lastModified(String path) {
|
|
|
|
S3Object s3Object = s3.getObject(bucket, path);
|
|
|
|
if (s3Object == null) {
|
|
|
|
return -1L;
|
|
|
|
}
|
|
|
|
return s3Object.getObjectMetadata().getLastModified().getTime();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public long length(String path) {
|
|
|
|
S3Object s3Object = s3.getObject(bucket, path);
|
|
|
|
if (s3Object == null) {
|
|
|
|
return -1L;
|
|
|
|
}
|
|
|
|
return s3Object.getObjectMetadata().getContentLength();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public boolean rename(String path, String newPath) throws ResourceIOException {
|
|
|
|
try {
|
|
|
|
CopyObjectRequest copyObjRequest = new CopyObjectRequest(bucket,
|
|
|
|
path, bucket, newPath);
|
|
|
|
s3.copyObject(copyObjRequest);
|
|
|
|
s3.deleteObject(new DeleteObjectRequest(bucket, path));
|
|
|
|
} catch (Exception e) {
|
|
|
|
LogKit.error(e.getMessage(), e);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void shutDown() {
|
|
|
|
s3.shutdown();
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public String getIdentity() {
|
|
|
|
return S3RepositoryFactory.IDENTITY;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|