Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add builder support to Compose object api #979

Merged
merged 8 commits into from
Jun 22, 2020
Merged
Show file tree
Hide file tree
Changes from 6 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
6 changes: 6 additions & 0 deletions api/src/main/java/io/minio/BaseArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,12 @@ protected void validateNullOrNotEmptyString(String arg, String argName) {
}
}

protected void validateNullOrPositive(Number arg, String argName) {
if (arg != null && arg.longValue() < 0) {
throw new IllegalArgumentException(argName + " cannot be non-negative.");
}
}

public Builder() {
this.operations = new ArrayList<>();
}
Expand Down
51 changes: 51 additions & 0 deletions api/src/main/java/io/minio/ComposeObjectArgs.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/*
* MinIO Java SDK for Amazon S3 Compatible Cloud Storage, (C) 2020 MinIO, Inc.
*
* 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
*
* http://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 io.minio;

import java.util.List;

public class ComposeObjectArgs extends ObjectWriteArgs {
List<ComposeSource> sources;

public List<ComposeSource> sources() {
return sources;
}

public static Builder builder() {
return new Builder();
}

public static final class Builder extends ObjectWriteArgs.Builder<Builder, ComposeObjectArgs> {
@Override
protected void validate(ComposeObjectArgs args) {
super.validate(args);
validateSources(args.sources);
}

public Builder sources(List<ComposeSource> sources) {
validateSources(sources);
operations.add(args -> args.sources = sources);
return this;
}

private void validateSources(List<ComposeSource> sources) {
if (sources == null || sources.isEmpty()) {
throw new IllegalArgumentException("compose sources cannot be empty");
}
}
}
sinhaashish marked this conversation as resolved.
Show resolved Hide resolved
}
215 changes: 103 additions & 112 deletions api/src/main/java/io/minio/ComposeSource.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,105 +17,104 @@

package io.minio;

import java.util.Collections;
import java.util.Map;
import java.util.TreeMap;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Multimaps;
import java.time.ZonedDateTime;

/** Source information to compose object. */
public class ComposeSource {
private String bucketName;
private String objectName;
public class ComposeSource extends ObjectVersionArgs {
private Long offset;
private Long length;
private Map<String, String> headerMap;
private CopyConditions copyConditions;
private ServerSideEncryptionCustomerKey ssec;
private long objectSize;
private Map<String, String> headers;
private String matchETag;
private String notMatchETag;
private ZonedDateTime modifiedSince;
private ZonedDateTime unmodifiedSince;
private ServerSideEncryptionCustomerKey ssec;

private Multimap<String, String> headers;

public Long offset() {
return offset;
}

public Long length() {
return length;
}

public long objectSize() {
return objectSize;
}

public String matchETag() {
return matchETag;
}

public String notMatchETag() {
return notMatchETag;
}

public ZonedDateTime modifiedSince() {
return modifiedSince;
}

/** Create new ComposeSource for given bucket and object. */
public ComposeSource(String bucketName, String objectName) throws IllegalArgumentException {
this(bucketName, objectName, null, null, null, null, null);
public ZonedDateTime unmodifiedSince() {
return unmodifiedSince;
}

/** Create new ComposeSource for given bucket, object, offset and length. */
public ComposeSource(String bucketName, String objectName, Long offset, Long length)
throws IllegalArgumentException {
this(bucketName, objectName, offset, length, null, null, null);
public Multimap<String, String> headers() {
return headers;
}

/** Create new ComposeSource for given bucket, object, offset, length and headerMap. */
public ComposeSource(
String bucketName, String objectName, Long offset, Long length, Map<String, String> headerMap)
throws IllegalArgumentException {
this(bucketName, objectName, offset, length, headerMap, null, null);
public ServerSideEncryptionCustomerKey ssec() {
return ssec;
}

/**
* Create new ComposeSource for given bucket, object, offset, length, headerMap and
* CopyConditions.
*/
public ComposeSource(
String bucketName,
String objectName,
Long offset,
Long length,
Map<String, String> headerMap,
CopyConditions copyConditions)
throws IllegalArgumentException {
this(bucketName, objectName, offset, length, headerMap, copyConditions, null);
public static Builder builder() {
return new Builder();
}

/**
* Creates new ComposeSource for given bucket, object, offset, length, headerMap, CopyConditions
* and server side encryption.
*
* @throws IllegalArgumentException upon invalid value is passed to a method.
*/
public ComposeSource(
String bucketName,
String objectName,
Long offset,
Long length,
Map<String, String> headerMap,
CopyConditions copyConditions,
ServerSideEncryptionCustomerKey ssec)
throws IllegalArgumentException {
if (bucketName == null) {
throw new IllegalArgumentException("Source bucket name cannot be empty");
/** Constructs header. */
public void buildHeaders(long objectSize, String etag) throws IllegalArgumentException {
validateSize(objectSize);
Multimap<String, String> headers = HashMultimap.create();
headers.put("x-amz-copy-source", S3Escaper.encodePath(bucketName + "/" + objectName));
headers.put("x-amz-copy-source-if-match", etag);

if (extraHeaders() != null) {
headers.putAll(extraHeaders());
}

if (objectName == null) {
throw new IllegalArgumentException("Source object name cannot be empty");
if (matchETag != null) {
headers.put("x-amz-copy-source-if-match", matchETag);
}

if (offset != null && offset < 0) {
throw new IllegalArgumentException("Offset cannot be negative");
if (ssec != null) {
headers.putAll(Multimaps.forMap(ssec.copySourceHeaders()));
}

if (length != null && length < 0) {
throw new IllegalArgumentException("Length cannot be negative");
if (notMatchETag != null) {
headers.put("x-amz-copy-source-if-none-match", notMatchETag);
}

if (length != null && offset == null) {
offset = 0L;
if (modifiedSince != null) {
headers.put(
"x-amz-copy-source-if-modified-since",
modifiedSince.format(Time.HTTP_HEADER_DATE_FORMAT));
}

this.bucketName = bucketName;
this.objectName = objectName;
this.offset = offset;
this.length = length;
if (headerMap != null) {
this.headerMap = Collections.unmodifiableMap(headerMap);
} else {
this.headerMap = null;
if (unmodifiedSince != null) {
headers.put(
"x-amz-copy-source-if-unmodified-since",
unmodifiedSince.format(Time.HTTP_HEADER_DATE_FORMAT));
}
this.copyConditions = copyConditions;
this.ssec = ssec;

this.objectSize = objectSize;
this.headers = headers;
}

/** Constructs header . */
public void buildHeaders(long objectSize, String etag) throws IllegalArgumentException {
private void validateSize(long objectSize) throws IllegalArgumentException {
if (offset != null && offset >= objectSize) {
throw new IllegalArgumentException(
"source "
Expand Down Expand Up @@ -153,56 +152,48 @@ public void buildHeaders(long objectSize, String etag) throws IllegalArgumentExc
+ objectSize);
}
}
}

Map<String, String> headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
headers.put("x-amz-copy-source", S3Escaper.encodePath(bucketName + "/" + objectName));
headers.put("x-amz-copy-source-if-match", etag);
/** Argument builder of {@link ComposeSource}. */
public static final class Builder extends ObjectVersionArgs.Builder<Builder, ComposeSource> {

if (headerMap != null) {
headers.putAll(headerMap);
public Builder offset(long offset) {
validateNullOrPositive(offset, "offset");
operations.add(args -> args.offset = offset);
return this;
}

if (copyConditions != null) {
headers.putAll(copyConditions.getConditions());
public Builder length(long length) {
validateNullOrPositive(length, "length");
operations.add(args -> args.length = length);
return this;
}

if (ssec != null) {
headers.putAll(ssec.copySourceHeaders());
public Builder ssec(ServerSideEncryptionCustomerKey ssec) {
operations.add(args -> args.ssec = ssec);
return this;
}

this.objectSize = objectSize;
this.headers = Collections.unmodifiableMap(headers);
}

public String bucketName() {
return bucketName;
}

public String objectName() {
return objectName;
}

public Long offset() {
return offset;
}

public Long length() {
return length;
}

public CopyConditions copyConditions() {
return copyConditions;
}
public Builder matchETag(String etag) {
validateNullOrNotEmptyString(etag, "etag");
operations.add(args -> args.matchETag = etag);
return this;
}

public ServerSideEncryptionCustomerKey ssec() {
return ssec;
}
public Builder notMatchETag(String etag) {
validateNullOrNotEmptyString(etag, "etag");
operations.add(args -> args.notMatchETag = etag);
return this;
}

public Map<String, String> headers() {
return headers;
}
public Builder modifiedSince(ZonedDateTime modifiedTime) {
operations.add(args -> args.modifiedSince = modifiedTime);
return this;
}

public long objectSize() {
return objectSize;
public Builder unmodifiedSince(ZonedDateTime unmodifiedTime) {
operations.add(args -> args.unmodifiedSince = unmodifiedTime);
return this;
}
}
}
Loading