Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 25 additions & 38 deletions src/main/java/loci/common/S3Handle.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,15 +40,14 @@
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.regex.Pattern;

import io.minio.MinioClient;
import io.minio.errors.MinioException;
import io.minio.ObjectStat;
import org.xmlpull.v1.XmlPullParserException;
import loci.common.services.DependencyException;
import loci.common.services.S3ClientService;
import loci.common.services.S3ClientServiceException;
import loci.common.services.S3ClientStat;

import loci.common.services.ServiceFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -103,11 +102,11 @@ class DelayedObjectNotFound extends IOException {
/** remaining path, or key, for this accessed resource */
private final String path;

/** Minio client */
private MinioClient s3Client;
/** S3 client */
private S3ClientService s3Client;

/** Remote file stat */
private ObjectStat stat;
private S3ClientStat stat;

/** Is this a directory (currently only buckets are considered directories */
private boolean isBucket;
Expand Down Expand Up @@ -228,11 +227,7 @@ else if (scheme.startsWith("s3+")) {
try {
this.initialize();
}
catch (
MinioException |
InvalidKeyException |
NoSuchAlgorithmException |
XmlPullParserException e) {
catch (S3ClientServiceException e) {
this.objectNotFound = e;
LOGGER.debug("Object not found: [{}] {}", this, e);
}
Expand All @@ -245,32 +240,33 @@ else if (scheme.startsWith("s3+")) {
* @throws IOException if there was an error connecting to the server
*/
protected void connect() throws IOException {
final String appName = "Bio-Formats";
// TODO: Replace "dev" with a version
final String appVersion = "dev";
try {
s3Client = new MinioClient(server, port, accessKey, secretKey);
// TODO: Replace "dev" with a version
s3Client.setAppInfo("Bio-Formats", "dev");
ServiceFactory factory = new ServiceFactory();
s3Client = factory.getInstance(S3ClientService.class);
s3Client.initialize(server, port, accessKey, secretKey, appName, appVersion);
}
catch (MinioException e) {
catch (S3ClientServiceException e) {
throw new IOException(String.format(
"Failed to connect: %s", this), e);
}
catch (DependencyException e) {
throw new IOException(String.format(
"S3 requires additional dependencies: %s", this), e);
}
LOGGER.trace("connected: server:{} port:{}", server, port);
}

/**
* Check bucket or object exists
* @throws IOException if unable to get the object
* @throws MinioException if unable to get the object
* @throws InvalidKeyException if unable to get the object
* @throws NoSuchAlgorithmException if unable to get the object
* @throws XmlPullParserException if unable to get the object
* @throws S3ClientServiceException if unable to get the object
*/
protected void initialize() throws
IOException,
MinioException,
InvalidKeyException,
NoSuchAlgorithmException,
XmlPullParserException {
S3ClientServiceException {
if (path == null) {
isBucket = s3Client.bucketExists(bucket);
}
Expand Down Expand Up @@ -347,16 +343,11 @@ protected void downloadObject(Path destination) throws HandleException, IOExcept
if (path == null) {
throw new HandleException("Download path=null not allowed");
}
Files.createDirectories(destination.getParent());
try {
Files.createDirectories(destination.getParent());
s3Client.getObject(bucket, path, destination.toString());
}
catch (
IOException |
InvalidKeyException |
MinioException |
NoSuchAlgorithmException |
XmlPullParserException e) {
catch (S3ClientServiceException e) {
Comment thread
manics marked this conversation as resolved.
throw new HandleException("Download failed " + toString(), e);
}
}
Expand Down Expand Up @@ -437,11 +428,7 @@ protected void resetStream(long offset) throws IOException {
fp = offset;
mark = offset;
}
catch (
InvalidKeyException |
MinioException |
NoSuchAlgorithmException |
XmlPullParserException e) {
catch (S3ClientServiceException e) {
throw new IOException(String.format(
"failed to load s3: %s\n\t%s", uri, this), e);
}
Expand Down
97 changes: 97 additions & 0 deletions src/main/java/loci/common/services/S3ClientService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
/*
* #%L
* S3 client service
* %%
* Copyright (C) 2019 Open Microscopy Environment:
* - Board of Regents of the University of Wisconsin-Madison
* - Glencoe Software, Inc.
* - University of Dundee
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/

package loci.common.services;

import java.io.IOException;
import java.io.InputStream;

/**
* An S3 client
*/
public interface S3ClientService extends Service {

/**
* Initialise the S3 client
* @param server servername
* @param port port
* @param accessKey access key
* @param secretKey secret key
* @param appName user agent application name
* @param appVersion user agent application version
* @throws S3ClientServiceException if an S3 error occurred
*/
void initialize(String server, int port, String accessKey, String secretKey,
String appName, String appVersion)
Comment thread
manics marked this conversation as resolved.
throws S3ClientServiceException;

/**
* Check whether a bucket exists
* @param bucket Bucket name
* @return true if bucket exists
* @throws S3ClientServiceException if an S3 error occurred
* @throws IOException if an S3 error occurred
*/
boolean bucketExists(String bucket) throws S3ClientServiceException, IOException;

/**
* Stat the object
* @param bucket Bucket name
* @param object Object path
* @return S3ClientStat object
* @throws S3ClientServiceException if an S3 error occurred
* @throws IOException if an S3 error occurred
*/
S3ClientStat statObject(String bucket, String object) throws S3ClientServiceException, IOException;

/**
* Read an object
* @param bucket Bucket name
* @param object Object path
* @param offset Start reading at this offset
* @return InputStream to the object
* @throws S3ClientServiceException if an S3 error occurred
* @throws IOException if an S3 error occurred
*/
InputStream getObject(String bucket, String object, long offset) throws S3ClientServiceException, IOException;

/**
* Download an object
* @param bucket Bucket name
* @param object Object path
* @param filename Destination file
* @throws S3ClientServiceException if an S3 error occurred
* @throws IOException if an S3 error occurred
*/
void getObject(String bucket, String object, String filename) throws S3ClientServiceException, IOException;

}
67 changes: 67 additions & 0 deletions src/main/java/loci/common/services/S3ClientServiceException.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/*
* #%L
* S3 client stat object
* %%
* Copyright (C) 2019 Open Microscopy Environment:
* - Board of Regents of the University of Wisconsin-Madison
* - Glencoe Software, Inc.
* - University of Dundee
* %%
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* #L%
*/

package loci.common.services;

/**
* Exception thrown when internal error specific to the S3 client is raised
*/
public class S3ClientServiceException extends ServiceException
{
/**
* Constructor.
* @param message Error message.
*/
public S3ClientServiceException(String message)
{
super(message);
}

/**
* Constructor.
* @param message Error message.
* @param cause Upstream exception.
*/
public S3ClientServiceException(String message, Throwable cause)
{
super(message, cause);
}

/**
* Constructor.
* @param cause Upstream exception.
*/
public S3ClientServiceException(Throwable cause)
{
super(cause);
}
}
Loading