Skip to content

Commit b8c0c94

Browse files
Sync APIs with S3 specification
Co-authored-by: Shireesh Anjal <[email protected]> Signed-off-by: Bala.FA <[email protected]>
1 parent f37052f commit b8c0c94

15 files changed

+308
-62
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
MinIO Java SDK is Simple Storage Service (aka S3) client to perform bucket and object operations to any Amazon S3 compatible object storage service.
44

5-
For a complete list of APIs and examples, please take a look at the [Java Client API Reference](https://min.io/docs/minio/linux/developers/java/API.html) documentation.
5+
For a complete list of APIs and examples, please take a look at the [Java Client API Reference](https://docs.min.io/enterprise/aistor-object-store/developers/sdk/java/api/) documentation.
66

77
## Minimum Requirements
88
Java 1.8 or above.
@@ -105,12 +105,12 @@ $ mc ls play/asiatrip/
105105
```
106106

107107
## More References
108-
* [Java Client API Reference](https://min.io/docs/minio/linux/developers/java/API.html)
108+
* [Java Client API Reference](https://docs.min.io/enterprise/aistor-object-store/developers/sdk/java/api/)
109109
* [Javadoc](https://minio-java.min.io/)
110110
* [Examples](https://github.com/minio/minio-java/tree/release/examples)
111111

112112
## Explore Further
113-
* [Complete Documentation](https://min.io/docs/minio/kubernetes/upstream/index.html)
113+
* [Complete Documentation](https://docs.min.io/enterprise/aistor-object-store/)
114114
* [Build your own Photo API Service - Full Application Example ](https://github.com/minio/minio-java-rest-example)
115115

116116
## Contribute

api/src/main/java/io/minio/BaseS3Client.java

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,10 @@ private void onResponse(final Response response) throws IOException {
413413
code = result[0];
414414
message = result[1];
415415
break;
416+
case 403:
417+
code = "AccessDenied";
418+
message = "Access denied";
419+
break;
416420
case 404:
417421
if (s3request.object() != null) {
418422
code = "NoSuchKey";
@@ -425,8 +429,8 @@ private void onResponse(final Response response) throws IOException {
425429
message = "Request resource not found";
426430
}
427431
break;
428-
case 501:
429432
case 405:
433+
case 501:
430434
code = "MethodNotAllowed";
431435
message = "The specified method is not allowed against this resource";
432436
break;
@@ -439,10 +443,6 @@ private void onResponse(final Response response) throws IOException {
439443
message = "Request resource conflicts";
440444
}
441445
break;
442-
case 403:
443-
code = "AccessDenied";
444-
message = "Access denied";
445-
break;
446446
case 412:
447447
code = "PreconditionFailed";
448448
message = "At least one of the preconditions you specified did not hold";
@@ -664,13 +664,18 @@ public CompletableFuture<AbortMultipartUploadResponse> abortMultipartUpload(
664664
public CompletableFuture<ObjectWriteResponse> completeMultipartUpload(
665665
CompleteMultipartUploadArgs args) {
666666
checkArgs(args);
667+
args.validateSsec(baseUrl.isHttps());
667668
Http.Body body = null;
668669
try {
669670
body = new Http.Body(new CompleteMultipartUpload(args.parts()), null, null, null);
670671
} catch (MinioException e) {
671672
return Utils.failedFuture(e);
672673
}
673-
return executePostAsync(args, null, new Http.QueryParameters(UPLOAD_ID, args.uploadId()), body)
674+
return executePostAsync(
675+
args,
676+
args.ssec() == null ? null : args.ssec().headers(),
677+
new Http.QueryParameters(UPLOAD_ID, args.uploadId()),
678+
body)
674679
.thenApply(
675680
response -> {
676681
try {
@@ -802,7 +807,7 @@ public CompletableFuture<GenericResponse> createBucket(CreateBucketArgs args) {
802807
if (locationConstraint.equals(Http.US_EAST_1)) {
803808
config =
804809
new CreateBucketConfiguration(
805-
locationConstraint, args.locationConfig(), args.bucketConfig());
810+
locationConstraint, args.locationConfig(), args.bucketConfig(), args.tags());
806811
}
807812

808813
Http.Body body = null;
@@ -951,6 +956,20 @@ public CompletableFuture<String> getBucketLocation(GetBucketLocationArgs args) {
951956
});
952957
}
953958

959+
/**
960+
* Do <a href="https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html">HeadBucket S3
961+
* API</a> asynchronously.
962+
*
963+
* @param args {@link HeadBucketArgs} object.
964+
* @return {@link CompletableFuture}&lt;{@link HeadBucketResponse}&gt; object.
965+
*/
966+
public CompletableFuture<HeadBucketResponse> headBucket(HeadBucketArgs args) {
967+
checkArgs(args);
968+
return executeHeadAsync(args, null, null)
969+
.thenApply(
970+
response -> new HeadBucketResponse(response.headers(), args.bucket(), args.region()));
971+
}
972+
954973
/**
955974
* Do <a href="https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html">HeadObject S3
956975
* API</a> asynchronously.

api/src/main/java/io/minio/BucketExistsArgs.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,11 @@
1717
package io.minio;
1818

1919
/** Arguments of {@link MinioAsyncClient#bucketExists} and {@link MinioClient#bucketExists}. */
20-
public class BucketExistsArgs extends BucketArgs {
20+
public class BucketExistsArgs extends HeadBucketBaseArgs {
2121
public static Builder builder() {
2222
return new Builder();
2323
}
2424

2525
/** Builder of {@link BucketExistsArgs}. */
26-
public static final class Builder extends BucketArgs.Builder<Builder, BucketExistsArgs> {}
26+
public static final class Builder extends HeadBucketBaseArgs.Builder<Builder, BucketExistsArgs> {}
2727
}

api/src/main/java/io/minio/CompleteMultipartUploadArgs.java

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
public class CompleteMultipartUploadArgs extends ObjectArgs {
2525
private String uploadId;
2626
private Part[] parts;
27+
private ServerSideEncryption.CustomerKey ssec;
2728

2829
protected CompleteMultipartUploadArgs() {}
2930

@@ -37,6 +38,9 @@ public CompleteMultipartUploadArgs(PutObjectBaseArgs args, String uploadId, Part
3738
super(args);
3839
this.uploadId = uploadId;
3940
this.parts = parts;
41+
if (args.sse() != null && args.sse() instanceof ServerSideEncryption.CustomerKey) {
42+
this.ssec = (ServerSideEncryption.CustomerKey) args.sse();
43+
}
4044
}
4145

4246
public String uploadId() {
@@ -47,6 +51,14 @@ public Part[] parts() {
4751
return parts;
4852
}
4953

54+
public ServerSideEncryption.CustomerKey ssec() {
55+
return ssec;
56+
}
57+
58+
public void validateSsec(boolean isHttps) {
59+
checkSse(ssec, isHttps);
60+
}
61+
5062
public static Builder builder() {
5163
return new Builder();
5264
}
@@ -72,6 +84,11 @@ public Builder parts(Part[] parts) {
7284
operations.add(args -> args.parts = parts);
7385
return this;
7486
}
87+
88+
public Builder ssec(ServerSideEncryption.CustomerKey ssec) {
89+
operations.add(args -> args.ssec = ssec);
90+
return this;
91+
}
7592
}
7693

7794
@Override
@@ -80,11 +97,13 @@ public boolean equals(Object o) {
8097
if (!(o instanceof CompleteMultipartUploadArgs)) return false;
8198
if (!super.equals(o)) return false;
8299
CompleteMultipartUploadArgs that = (CompleteMultipartUploadArgs) o;
83-
return Objects.equals(uploadId, that.uploadId) && Arrays.equals(parts, that.parts);
100+
return Objects.equals(uploadId, that.uploadId)
101+
&& Arrays.equals(parts, that.parts)
102+
&& Objects.equals(ssec, that.ssec);
84103
}
85104

86105
@Override
87106
public int hashCode() {
88-
return Objects.hash(super.hashCode(), uploadId, parts);
107+
return Objects.hash(super.hashCode(), uploadId, parts, ssec);
89108
}
90109
}

api/src/main/java/io/minio/CreateBucketBaseArgs.java

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,15 @@
1717
package io.minio;
1818

1919
import io.minio.messages.CreateBucketConfiguration;
20+
import io.minio.messages.Tags;
2021
import java.util.Objects;
2122

2223
/** Common arguments of {@link CreateBucketArgs} and {@link MakeBucketArgs}. */
2324
public abstract class CreateBucketBaseArgs extends BucketArgs {
2425
protected boolean objectLock;
2526
protected CreateBucketConfiguration.Location locationConfig;
2627
protected CreateBucketConfiguration.Bucket bucket;
28+
protected Tags tags;
2729

2830
protected CreateBucketBaseArgs() {}
2931

@@ -32,6 +34,7 @@ protected CreateBucketBaseArgs(CreateBucketBaseArgs args) {
3234
this.objectLock = args.objectLock;
3335
this.locationConfig = args.locationConfig;
3436
this.bucket = args.bucket;
37+
this.tags = args.tags;
3538
}
3639

3740
public boolean objectLock() {
@@ -46,6 +49,10 @@ public CreateBucketConfiguration.Bucket bucketConfig() {
4649
return bucket;
4750
}
4851

52+
public Tags tags() {
53+
return tags;
54+
}
55+
4956
/** Base argument builder of {@link CreateBucketBaseArgs}. */
5057
@SuppressWarnings("unchecked") // Its safe to type cast to B as B is inherited by this class
5158
public abstract static class Builder<B extends Builder<B, A>, A extends CreateBucketBaseArgs>
@@ -69,6 +76,11 @@ public B bucketConfig(CreateBucketConfiguration.Bucket bucket) {
6976
operations.add(args -> args.bucket = bucket);
7077
return (B) this;
7178
}
79+
80+
public B tags(Tags tags) {
81+
operations.add(args -> args.tags = tags);
82+
return (B) this;
83+
}
7284
}
7385

7486
@Override
@@ -79,11 +91,12 @@ public boolean equals(Object o) {
7991
CreateBucketBaseArgs that = (CreateBucketBaseArgs) o;
8092
return objectLock == that.objectLock
8193
&& Objects.equals(locationConfig, that.locationConfig)
82-
&& Objects.equals(bucket, that.bucket);
94+
&& Objects.equals(bucket, that.bucket)
95+
&& Objects.equals(tags, that.tags);
8396
}
8497

8598
@Override
8699
public int hashCode() {
87-
return Objects.hash(super.hashCode(), objectLock, locationConfig, bucket);
100+
return Objects.hash(super.hashCode(), objectLock, locationConfig, bucket, tags);
88101
}
89102
}

api/src/main/java/io/minio/DownloadObjectArgs.java

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package io.minio;
1818

19+
import java.time.ZonedDateTime;
1920
import java.util.Objects;
2021

2122
/**
@@ -25,6 +26,10 @@
2526
public class DownloadObjectArgs extends ObjectReadArgs {
2627
private String filename;
2728
private boolean overwrite;
29+
protected String matchETag;
30+
protected String notMatchETag;
31+
protected ZonedDateTime modifiedSince;
32+
protected ZonedDateTime unmodifiedSince;
2833

2934
public String filename() {
3035
return filename;
@@ -34,6 +39,22 @@ public boolean overwrite() {
3439
return overwrite;
3540
}
3641

42+
public String matchETag() {
43+
return matchETag;
44+
}
45+
46+
public String notMatchETag() {
47+
return notMatchETag;
48+
}
49+
50+
public ZonedDateTime modifiedSince() {
51+
return modifiedSince;
52+
}
53+
54+
public ZonedDateTime unmodifiedSince() {
55+
return unmodifiedSince;
56+
}
57+
3758
public static Builder builder() {
3859
return new Builder();
3960
}
@@ -54,6 +75,28 @@ public Builder overwrite(boolean flag) {
5475
operations.add(args -> args.overwrite = flag);
5576
return this;
5677
}
78+
79+
public Builder matchETag(String etag) {
80+
Utils.validateNullOrNotEmptyString(etag, "etag");
81+
operations.add(args -> args.matchETag = etag);
82+
return this;
83+
}
84+
85+
public Builder notMatchETag(String etag) {
86+
Utils.validateNullOrNotEmptyString(etag, "etag");
87+
operations.add(args -> args.notMatchETag = etag);
88+
return this;
89+
}
90+
91+
public Builder modifiedSince(ZonedDateTime modifiedTime) {
92+
operations.add(args -> args.modifiedSince = modifiedTime);
93+
return this;
94+
}
95+
96+
public Builder unmodifiedSince(ZonedDateTime unmodifiedTime) {
97+
operations.add(args -> args.unmodifiedSince = unmodifiedTime);
98+
return this;
99+
}
57100
}
58101

59102
@Override
@@ -62,12 +105,23 @@ public boolean equals(Object o) {
62105
if (!(o instanceof DownloadObjectArgs)) return false;
63106
if (!super.equals(o)) return false;
64107
DownloadObjectArgs that = (DownloadObjectArgs) o;
65-
if (!Objects.equals(filename, that.filename)) return false;
66-
return overwrite == that.overwrite;
108+
return Objects.equals(filename, that.filename)
109+
&& overwrite == that.overwrite
110+
&& Objects.equals(matchETag, that.matchETag)
111+
&& Objects.equals(notMatchETag, that.notMatchETag)
112+
&& Objects.equals(modifiedSince, that.modifiedSince)
113+
&& Objects.equals(unmodifiedSince, that.unmodifiedSince);
67114
}
68115

69116
@Override
70117
public int hashCode() {
71-
return Objects.hash(super.hashCode(), filename, overwrite);
118+
return Objects.hash(
119+
super.hashCode(),
120+
filename,
121+
overwrite,
122+
matchETag,
123+
notMatchETag,
124+
modifiedSince,
125+
unmodifiedSince);
72126
}
73127
}

api/src/main/java/io/minio/GenericUploadResponse.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818

1919
import io.minio.messages.CompleteMultipartUploadResult;
2020
import io.minio.messages.CopyObjectResult;
21+
import java.time.ZonedDateTime;
2122
import okhttp3.Headers;
2223

2324
/** Common response of {@link ObjectWriteResponse} and {@link PutObjectFanOutResponse}. */
2425
public class GenericUploadResponse extends GenericResponse {
2526
private String etag;
27+
private ZonedDateTime lastModified;
2628
private String checksumCRC32;
2729
private String checksumCRC32C;
2830
private String checksumCRC64NVME;
@@ -53,6 +55,7 @@ public GenericUploadResponse(
5355
CopyObjectResult result) {
5456
super(headers, bucket, region, object);
5557
this.etag = etag;
58+
this.lastModified = result.lastModified();
5659
if (result != null) {
5760
this.checksumType = result.checksumType();
5861
this.checksumCRC32 = result.checksumCRC32();
@@ -86,6 +89,10 @@ public String etag() {
8689
return etag;
8790
}
8891

92+
public ZonedDateTime lastModified() {
93+
return lastModified;
94+
}
95+
8996
public String checksumCRC32() {
9097
return checksumCRC32;
9198
}

0 commit comments

Comments
 (0)