-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* implement delete objects
- Loading branch information
Showing
14 changed files
with
408 additions
and
1 deletion.
There are no files selected for viewing
56 changes: 56 additions & 0 deletions
56
local-s3-core/src/main/java/com/robothy/s3/core/service/DeleteObjectsService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
package com.robothy.s3.core.service; | ||
|
||
import com.robothy.s3.core.exception.LocalS3Exception; | ||
import com.robothy.s3.core.model.answers.DeleteObjectAns; | ||
import com.robothy.s3.datatypes.ObjectIdentifier; | ||
import com.robothy.s3.datatypes.request.DeleteObjectsRequest; | ||
import com.robothy.s3.datatypes.response.DeleteResult; | ||
import com.robothy.s3.datatypes.response.S3Error; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
|
||
public interface DeleteObjectsService extends DeleteObjectService { | ||
|
||
/** | ||
* Delete objects from a specified bucket. | ||
* | ||
* @param bucketName bucket name. | ||
* @param request delete objects request. | ||
* @return delete results. | ||
*/ | ||
default List<Object> deleteObjects(String bucketName, DeleteObjectsRequest request) { | ||
|
||
List<Object> results = new ArrayList<>(request.getObjects().size()); | ||
for (ObjectIdentifier id : request.getObjects()) { | ||
String key = id.getKey(); | ||
String versionId = id.getVersionId().orElse(null); | ||
try { | ||
DeleteObjectAns deleteObjectAns = deleteObject(bucketName, key, versionId); | ||
if (request.isQuiet()) { | ||
continue; | ||
} | ||
|
||
DeleteResult.Deleted deleted = new DeleteResult.Deleted(); | ||
deleted.setKey(key); | ||
deleted.setVersionId(versionId); | ||
if (deleteObjectAns.isDeleteMarker()) { | ||
deleted.setDeleteMarker(true); | ||
deleted.setDeleteMarkerVersionId(deleteObjectAns.getVersionId()); | ||
} | ||
results.add(deleted); | ||
} catch (Throwable e) { | ||
S3Error.S3ErrorBuilder builder = S3Error.builder() | ||
.bucketName(bucketName) | ||
.message(e.getMessage()) | ||
.key(key) | ||
.versionId(versionId); | ||
if (e instanceof LocalS3Exception) { | ||
builder.code(((LocalS3Exception) e).getS3ErrorCode().code()); | ||
} | ||
results.add(builder.build()); | ||
} | ||
} | ||
return results; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
49 changes: 49 additions & 0 deletions
49
local-s3-core/src/test/java/com/robothy/s3/core/service/DeleteObjectsServiceTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package com.robothy.s3.core.service; | ||
|
||
import static org.junit.jupiter.api.Assertions.assertEquals; | ||
import static org.junit.jupiter.api.Assertions.assertInstanceOf; | ||
import static org.junit.jupiter.api.Assertions.assertTrue; | ||
import com.robothy.s3.core.exception.S3ErrorCode; | ||
import com.robothy.s3.core.model.internal.ObjectMetadata; | ||
import com.robothy.s3.datatypes.ObjectIdentifier; | ||
import com.robothy.s3.datatypes.request.DeleteObjectsRequest; | ||
import com.robothy.s3.datatypes.response.DeleteResult; | ||
import com.robothy.s3.datatypes.response.S3Error; | ||
import java.util.List; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.MethodSource; | ||
|
||
class DeleteObjectsServiceTest extends LocalS3ServiceTestBase { | ||
|
||
@MethodSource("localS3Services") | ||
@ParameterizedTest | ||
void testDeleteObjects(BucketService bucketService, ObjectService objectService) { | ||
String bucketName = "my-bucket"; | ||
bucketService.createBucket(bucketName); | ||
|
||
List<ObjectIdentifier> objectsToDelete = List.of( | ||
new ObjectIdentifier("a.txt", "123"), | ||
new ObjectIdentifier("b.txt", null) | ||
); | ||
DeleteObjectsRequest request1 = new DeleteObjectsRequest(objectsToDelete, false); | ||
|
||
List<Object> results = objectService.deleteObjects(bucketName, request1); | ||
|
||
assertInstanceOf(S3Error.class, results.get(0)); | ||
S3Error s3Error = (S3Error) results.get(0); | ||
assertEquals("a.txt", s3Error.getKey()); | ||
assertEquals("123", s3Error.getVersionId()); | ||
assertEquals(S3ErrorCode.NoSuchKey.code(), s3Error.getCode()); | ||
|
||
assertInstanceOf(DeleteResult.Deleted.class, results.get(1)); | ||
DeleteResult.Deleted deleted = (DeleteResult.Deleted) results.get(1); | ||
assertTrue(deleted.isDeleteMarker()); | ||
assertEquals(ObjectMetadata.NULL_VERSION, deleted.getDeleteMarkerVersionId()); | ||
|
||
DeleteObjectsRequest request2 = new DeleteObjectsRequest(objectsToDelete, true); | ||
List<Object> results2 = objectService.deleteObjects(bucketName, request2); | ||
assertEquals(1, results2.size()); | ||
assertInstanceOf(S3Error.class, results2.get(0)); | ||
} | ||
|
||
} |
27 changes: 27 additions & 0 deletions
27
local-s3-datatypes/src/main/java/com/robothy/s3/datatypes/ObjectIdentifier.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package com.robothy.s3.datatypes; | ||
|
||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; | ||
import java.util.Optional; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
|
||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@Getter | ||
@Setter | ||
public class ObjectIdentifier { | ||
|
||
@JacksonXmlProperty(localName = "Key") | ||
private String key; | ||
|
||
@JacksonXmlProperty(localName = "VersionId") | ||
private String versionId; | ||
|
||
public Optional<String> getVersionId() { | ||
return Optional.ofNullable(versionId); | ||
} | ||
|
||
} |
28 changes: 28 additions & 0 deletions
28
local-s3-datatypes/src/main/java/com/robothy/s3/datatypes/request/DeleteObjectsRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package com.robothy.s3.datatypes.request; | ||
|
||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; | ||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; | ||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; | ||
import com.robothy.s3.datatypes.ObjectIdentifier; | ||
import java.util.ArrayList; | ||
import java.util.List; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
|
||
@Getter | ||
@Setter | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@JacksonXmlRootElement(localName = "Delete") | ||
public class DeleteObjectsRequest { | ||
|
||
@JacksonXmlElementWrapper(useWrapping = false) | ||
@JacksonXmlProperty(localName = "Object") | ||
private List<ObjectIdentifier> objects = new ArrayList<>(); | ||
|
||
@JacksonXmlProperty(localName = "Quiet") | ||
private boolean quiet; | ||
|
||
} |
83 changes: 83 additions & 0 deletions
83
local-s3-datatypes/src/main/java/com/robothy/s3/datatypes/response/DeleteResult.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package com.robothy.s3.datatypes.response; | ||
|
||
import com.fasterxml.jackson.core.JsonGenerator; | ||
import com.fasterxml.jackson.databind.SerializerProvider; | ||
import com.fasterxml.jackson.databind.annotation.JsonSerialize; | ||
import com.fasterxml.jackson.databind.ser.std.StdSerializer; | ||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlElementWrapper; | ||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; | ||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; | ||
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator; | ||
import java.io.IOException; | ||
import java.lang.reflect.Field; | ||
import java.util.List; | ||
import java.util.Objects; | ||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.NoArgsConstructor; | ||
import lombok.Setter; | ||
import lombok.SneakyThrows; | ||
|
||
@Setter | ||
@Getter | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@JacksonXmlRootElement(localName = "DeleteResult") | ||
@JsonSerialize(using = DeleteResult.DeleteResultSerializer.class) | ||
public class DeleteResult { | ||
|
||
@JacksonXmlElementWrapper(useWrapping = false) | ||
private List<Object> deletedList; | ||
|
||
@Setter | ||
@Getter | ||
@JacksonXmlRootElement(localName = "Deleted") | ||
public static class Deleted { | ||
|
||
@JacksonXmlProperty(localName = "DeleteMarker") | ||
private boolean deleteMarker; | ||
|
||
@JacksonXmlProperty(localName = "DeleteMarkerVersionId") | ||
private String deleteMarkerVersionId; | ||
|
||
@JacksonXmlProperty(localName = "Key") | ||
private String key; | ||
|
||
@JacksonXmlProperty(localName = "VersionId") | ||
private String versionId; | ||
|
||
} | ||
|
||
static class DeleteResultSerializer extends StdSerializer<DeleteResult> { | ||
|
||
DeleteResultSerializer() { | ||
this(null); | ||
} | ||
|
||
protected DeleteResultSerializer(Class<DeleteResult> t) { | ||
super(t); | ||
} | ||
|
||
@SneakyThrows | ||
@Override | ||
public void serialize(DeleteResult deleteResult, JsonGenerator gen, SerializerProvider provider) throws IOException { | ||
|
||
if (gen instanceof ToXmlGenerator) { | ||
gen.writeStartObject(); | ||
Field deletedListField = DeleteResult.class.getDeclaredField("deletedList"); | ||
deletedListField.setAccessible(true); | ||
for (Object item : (List)deletedListField.get(deleteResult)) { | ||
JacksonXmlRootElement jacksonXmlRootElement = item.getClass().getDeclaredAnnotation(JacksonXmlRootElement.class); | ||
Objects.requireNonNull(jacksonXmlRootElement, "Must add @JacksonXmlRootElement to " + item.getClass()); | ||
gen.writeFieldName(jacksonXmlRootElement.localName()); | ||
gen.writeObject(item); | ||
} | ||
|
||
gen.writeEndObject(); | ||
} | ||
|
||
} | ||
|
||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
40 changes: 40 additions & 0 deletions
40
...s3-datatypes/src/test/java/com/robothy/s3/datatypes/request/DeleteObjectsRequestTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
package com.robothy.s3.datatypes.request; | ||
|
||
import static org.junit.jupiter.api.Assertions.*; | ||
import com.fasterxml.jackson.core.JsonProcessingException; | ||
import com.fasterxml.jackson.dataformat.xml.XmlMapper; | ||
import com.robothy.s3.datatypes.ObjectIdentifier; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class DeleteObjectsRequestTest { | ||
|
||
@Test | ||
void testDeserializeDeleteObjectsRequest() throws JsonProcessingException { | ||
|
||
String xml = "<Delete>\n" + | ||
" <Object>\n" + | ||
" <Key>a.txt</Key>\n" + | ||
" <VersionId>null</VersionId>\n" + | ||
" </Object>\n" + | ||
" <Object>\n" + | ||
" <Key>b.txt</Key>\n" + | ||
" </Object>\n" + | ||
" <Quiet>true</Quiet>\n" + | ||
"</Delete>"; | ||
|
||
XmlMapper xmlMapper = new XmlMapper(); | ||
DeleteObjectsRequest request = xmlMapper.readValue(xml, DeleteObjectsRequest.class); | ||
assertEquals(2, request.getObjects().size()); | ||
ObjectIdentifier objectIdentifier1 = request.getObjects().get(0); | ||
assertEquals("a.txt", objectIdentifier1.getKey()); | ||
assertTrue(objectIdentifier1.getVersionId().isPresent()); | ||
assertEquals("null", objectIdentifier1.getVersionId().get()); | ||
|
||
ObjectIdentifier objectIdentifier2 = request.getObjects().get(1); | ||
assertEquals("b.txt", objectIdentifier2.getKey()); | ||
assertTrue(objectIdentifier2.getVersionId().isEmpty()); | ||
|
||
assertTrue(request.isQuiet()); | ||
} | ||
|
||
} |
20 changes: 20 additions & 0 deletions
20
local-s3-datatypes/src/test/java/com/robothy/s3/datatypes/response/DeleteResultTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package com.robothy.s3.datatypes.response; | ||
|
||
import com.fasterxml.jackson.dataformat.xml.XmlMapper; | ||
import java.util.List; | ||
import org.junit.jupiter.api.Assertions; | ||
import org.junit.jupiter.api.Test; | ||
|
||
class DeleteResultTest { | ||
|
||
@Test | ||
void testSerialization() { | ||
DeleteResult deleteResult = new DeleteResult(); | ||
deleteResult.setDeletedList(List.of(new S3Error(), new DeleteResult.Deleted())); | ||
|
||
XmlMapper xmlMapper = new XmlMapper(); | ||
Assertions.assertDoesNotThrow(() -> xmlMapper.writerWithDefaultPrettyPrinter() | ||
.writeValueAsString(deleteResult)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.