Skip to content

Commit 2754331

Browse files
balamuruganaanjalshireeshsivanantham-gnanavel
authored
Sync APIs with S3 specification (#1678)
Signed-off-by: Bala.FA <bala@minio.io> Co-authored-by: Shireesh Anjal <355479+anjalshireesh@users.noreply.github.com> Co-authored-by: Sivanantham Gnanavel <158702293+sivanantham-gnanavel@users.noreply.github.com>
1 parent f37052f commit 2754331

16 files changed

+329
-78
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: 32 additions & 15 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 {
@@ -794,16 +799,14 @@ public CompletableFuture<GenericResponse> createBucket(CreateBucketArgs args) {
794799
region = Http.US_EAST_1;
795800
}
796801

797-
Http.Headers headers =
798-
args.objectLock() ? new Http.Headers("x-amz-bucket-object-lock-enabled", "true") : null;
799-
final String locationConstraint = region;
802+
Http.Headers headers = new Http.Headers();
803+
if (args.objectLock()) headers.put("x-amz-bucket-object-lock-enabled", "true");
804+
if (args.forceCreate()) headers.put("x-minio-force-create", "true");
800805

801-
CreateBucketConfiguration config = null;
802-
if (locationConstraint.equals(Http.US_EAST_1)) {
803-
config =
804-
new CreateBucketConfiguration(
805-
locationConstraint, args.locationConfig(), args.bucketConfig());
806-
}
806+
final String locationConstraint = region;
807+
CreateBucketConfiguration config =
808+
new CreateBucketConfiguration(
809+
locationConstraint, args.locationConfig(), args.bucketConfig(), args.tags());
807810

808811
Http.Body body = null;
809812
try {
@@ -951,6 +954,20 @@ public CompletableFuture<String> getBucketLocation(GetBucketLocationArgs args) {
951954
});
952955
}
953956

957+
/**
958+
* Do <a href="https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadBucket.html">HeadBucket S3
959+
* API</a> asynchronously.
960+
*
961+
* @param args {@link HeadBucketArgs} object.
962+
* @return {@link CompletableFuture}&lt;{@link HeadBucketResponse}&gt; object.
963+
*/
964+
public CompletableFuture<HeadBucketResponse> headBucket(HeadBucketArgs args) {
965+
checkArgs(args);
966+
return executeHeadAsync(args, null, null)
967+
.thenApply(
968+
response -> new HeadBucketResponse(response.headers(), args.bucket(), args.region()));
969+
}
970+
954971
/**
955972
* Do <a href="https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html">HeadObject S3
956973
* 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: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,16 @@
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;
29+
protected boolean forceCreate;
2730

2831
protected CreateBucketBaseArgs() {}
2932

@@ -32,6 +35,8 @@ protected CreateBucketBaseArgs(CreateBucketBaseArgs args) {
3235
this.objectLock = args.objectLock;
3336
this.locationConfig = args.locationConfig;
3437
this.bucket = args.bucket;
38+
this.tags = args.tags;
39+
this.forceCreate = args.forceCreate;
3540
}
3641

3742
public boolean objectLock() {
@@ -46,6 +51,14 @@ public CreateBucketConfiguration.Bucket bucketConfig() {
4651
return bucket;
4752
}
4853

54+
public Tags tags() {
55+
return tags;
56+
}
57+
58+
public boolean forceCreate() {
59+
return forceCreate;
60+
}
61+
4962
/** Base argument builder of {@link CreateBucketBaseArgs}. */
5063
@SuppressWarnings("unchecked") // Its safe to type cast to B as B is inherited by this class
5164
public abstract static class Builder<B extends Builder<B, A>, A extends CreateBucketBaseArgs>
@@ -69,6 +82,16 @@ public B bucketConfig(CreateBucketConfiguration.Bucket bucket) {
6982
operations.add(args -> args.bucket = bucket);
7083
return (B) this;
7184
}
85+
86+
public B tags(Tags tags) {
87+
operations.add(args -> args.tags = tags);
88+
return (B) this;
89+
}
90+
91+
public B forceCreate(boolean forceCreate) {
92+
operations.add(args -> args.forceCreate = forceCreate);
93+
return (B) this;
94+
}
7295
}
7396

7497
@Override
@@ -79,11 +102,13 @@ public boolean equals(Object o) {
79102
CreateBucketBaseArgs that = (CreateBucketBaseArgs) o;
80103
return objectLock == that.objectLock
81104
&& Objects.equals(locationConfig, that.locationConfig)
82-
&& Objects.equals(bucket, that.bucket);
105+
&& Objects.equals(bucket, that.bucket)
106+
&& Objects.equals(tags, that.tags)
107+
&& forceCreate == that.forceCreate;
83108
}
84109

85110
@Override
86111
public int hashCode() {
87-
return Objects.hash(super.hashCode(), objectLock, locationConfig, bucket);
112+
return Objects.hash(super.hashCode(), objectLock, locationConfig, bucket, tags, forceCreate);
88113
}
89114
}

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
}

0 commit comments

Comments
 (0)