JAMES-2432 [Export] adding mailboxId, messageId, UID extra fields
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/f30001c2 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/f30001c2 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/f30001c2 Branch: refs/heads/master Commit: f30001c2258d68e98d6425e23f73933c52466c15 Parents: 7f945d3 Author: duc <[email protected]> Authored: Wed Jun 20 12:59:03 2018 +0700 Committer: Raphael Ouazana <[email protected]> Committed: Wed Jun 27 16:36:12 2018 +0200 ---------------------------------------------------------------------- .../mailbox/backup/MailboxIdExtraField.java | 105 ++++++++ .../mailbox/backup/MessageIdExtraField.java | 105 ++++++++ .../james/mailbox/backup/UidExtraField.java | 112 ++++++++ .../org/apache/james/mailbox/backup/Zipper.java | 8 + .../mailbox/backup/MailboxIdExtraFieldTest.java | 207 +++++++++++++++ .../mailbox/backup/MailboxMessageFixture.java | 13 +- .../mailbox/backup/MessageIdExtraFieldTest.java | 214 ++++++++++++++++ .../james/mailbox/backup/UidExtraFieldTest.java | 254 +++++++++++++++++++ .../apache/james/mailbox/backup/ZipperTest.java | 9 +- 9 files changed, 1023 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/f30001c2/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxIdExtraField.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxIdExtraField.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxIdExtraField.java new file mode 100644 index 0000000..5bdbd64 --- /dev/null +++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MailboxIdExtraField.java @@ -0,0 +1,105 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 org.apache.james.mailbox.backup; + +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.Optional; + +import org.apache.commons.compress.archivers.zip.ZipExtraField; +import org.apache.commons.compress.archivers.zip.ZipShort; + +public class MailboxIdExtraField implements ZipExtraField { + + public static final ZipShort ID = new ZipShort(0x6D61); // "am" in little-endian + + private Optional<String> mailboxId; + + public MailboxIdExtraField() { + this(Optional.empty()); + } + + public MailboxIdExtraField(String mailboxId) { + this(Optional.of(mailboxId)); + } + + public MailboxIdExtraField(Optional<String> mailboxId) { + this.mailboxId = mailboxId; + } + + @Override + public ZipShort getHeaderId() { + return ID; + } + + @Override + public ZipShort getLocalFileDataLength() { + return mailboxId + .map(value -> value.getBytes(StandardCharsets.UTF_8).length) + .map(ZipShort::new) + .orElseThrow(() -> new RuntimeException("Value must by initialized")); + } + + @Override + public ZipShort getCentralDirectoryLength() { + return getLocalFileDataLength(); + } + + @Override + public byte[] getLocalFileDataData() { + return mailboxId + .map(value -> value.getBytes(StandardCharsets.UTF_8)) + .orElseThrow(() -> new RuntimeException("Value must by initialized")); + } + + @Override + public byte[] getCentralDirectoryData() { + return getLocalFileDataData(); + } + + @Override + public void parseFromLocalFileData(byte[] buffer, int offset, int length) { + mailboxId = Optional.of(new String(buffer, offset, length, StandardCharsets.UTF_8)); + } + + @Override + public void parseFromCentralDirectoryData(byte[] buffer, int offset, int length) { + parseFromLocalFileData(buffer, offset, length); + } + + public Optional<String> getMailboxId() { + return mailboxId; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof MailboxIdExtraField) { + MailboxIdExtraField that = (MailboxIdExtraField) o; + + return Objects.equals(this.mailboxId, that.mailboxId); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(mailboxId); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/f30001c2/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MessageIdExtraField.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MessageIdExtraField.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MessageIdExtraField.java new file mode 100644 index 0000000..9f68016 --- /dev/null +++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/MessageIdExtraField.java @@ -0,0 +1,105 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 org.apache.james.mailbox.backup; + +import java.nio.charset.StandardCharsets; +import java.util.Objects; +import java.util.Optional; + +import org.apache.commons.compress.archivers.zip.ZipExtraField; +import org.apache.commons.compress.archivers.zip.ZipShort; + +public class MessageIdExtraField implements ZipExtraField { + + public static final ZipShort ID = new ZipShort(0x6C61); // "al" in little-endian + + private Optional<String> messageId; + + public MessageIdExtraField() { + this(Optional.empty()); + } + + public MessageIdExtraField(String messageId) { + this(Optional.of(messageId)); + } + + public MessageIdExtraField(Optional<String> messageId) { + this.messageId = messageId; + } + + @Override + public ZipShort getHeaderId() { + return ID; + } + + @Override + public ZipShort getLocalFileDataLength() { + return messageId + .map(value -> value.getBytes(StandardCharsets.UTF_8).length) + .map(ZipShort::new) + .orElseThrow(() -> new RuntimeException("Value must by initialized")); + } + + @Override + public ZipShort getCentralDirectoryLength() { + return getLocalFileDataLength(); + } + + @Override + public byte[] getLocalFileDataData() { + return messageId + .map(value -> value.getBytes(StandardCharsets.UTF_8)) + .orElseThrow(() -> new RuntimeException("Value must by initialized")); + } + + @Override + public byte[] getCentralDirectoryData() { + return getLocalFileDataData(); + } + + @Override + public void parseFromLocalFileData(byte[] buffer, int offset, int length) { + messageId = Optional.of(new String(buffer, offset, length, StandardCharsets.UTF_8)); + } + + @Override + public void parseFromCentralDirectoryData(byte[] buffer, int offset, int length) { + parseFromLocalFileData(buffer, offset, length); + } + + public Optional<String> getMessageId() { + return messageId; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof MessageIdExtraField) { + MessageIdExtraField that = (MessageIdExtraField) o; + + return Objects.equals(this.messageId, that.messageId); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(messageId); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/f30001c2/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/UidExtraField.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/UidExtraField.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/UidExtraField.java new file mode 100644 index 0000000..cd1607e --- /dev/null +++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/UidExtraField.java @@ -0,0 +1,112 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 org.apache.james.mailbox.backup; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.Objects; +import java.util.Optional; +import java.util.zip.ZipException; + +import org.apache.commons.compress.archivers.zip.ZipExtraField; +import org.apache.commons.compress.archivers.zip.ZipShort; + +public class UidExtraField implements ZipExtraField { + + public static final ZipShort ID = new ZipShort(0x6B61); // "ak" in little-endian + + private Optional<Long> uid; + + public UidExtraField() { + this(Optional.empty()); + } + + public UidExtraField(long uid) { + this(Optional.of(uid)); + } + + public UidExtraField(Optional<Long> uid) { + this.uid = uid; + } + + @Override + public ZipShort getHeaderId() { + return ID; + } + + @Override + public ZipShort getLocalFileDataLength() { + return new ZipShort(Long.BYTES); + } + + @Override + public ZipShort getCentralDirectoryLength() { + return getLocalFileDataLength(); + } + + @Override + public byte[] getLocalFileDataData() { + long value = uid.orElseThrow(() -> new RuntimeException("Value must by initialized")); + return ByteBuffer.allocate(Long.BYTES) + .order(ByteOrder.LITTLE_ENDIAN) + .putLong(value) + .array(); + } + + @Override + public byte[] getCentralDirectoryData() { + return getLocalFileDataData(); + } + + @Override + public void parseFromLocalFileData(byte[] buffer, int offset, int length) throws ZipException { + if (length != Long.BYTES) { + throw new ZipException("Unexpected data length for UidExtraField. Expected " + Long.BYTES + " but got " + length + "."); + } + uid = Optional.of(ByteBuffer + .wrap(buffer, offset, Long.BYTES) + .order(ByteOrder.LITTLE_ENDIAN) + .getLong()); + } + + @Override + public void parseFromCentralDirectoryData(byte[] buffer, int offset, int length) throws ZipException { + parseFromLocalFileData(buffer, offset, length); + } + + public Optional<Long> getUid() { + return uid; + } + + @Override + public final boolean equals(Object o) { + if (o instanceof UidExtraField) { + UidExtraField that = (UidExtraField) o; + + return Objects.equals(this.uid, that.uid); + } + return false; + } + + @Override + public final int hashCode() { + return Objects.hash(uid); + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/f30001c2/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Zipper.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Zipper.java b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Zipper.java index b25a9db..9b13bc2 100644 --- a/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Zipper.java +++ b/mailbox/backup/src/main/java/org/apache/james/mailbox/backup/Zipper.java @@ -36,6 +36,9 @@ import com.github.fge.lambdas.Throwing; public class Zipper implements Backup { public Zipper() { ExtraFieldUtils.register(SizeExtraField.class); + ExtraFieldUtils.register(UidExtraField.class); + ExtraFieldUtils.register(MessageIdExtraField.class); + ExtraFieldUtils.register(MailboxIdExtraField.class); } @Override @@ -61,7 +64,12 @@ public class Zipper implements Backup { private void storeInArchive(MailboxMessage message, ZipArchiveOutputStream archiveOutputStream) throws IOException { String entryId = message.getMessageId().serialize(); ZipArchiveEntry archiveEntry = (ZipArchiveEntry) archiveOutputStream.createArchiveEntry(new File(entryId), entryId); + archiveEntry.addExtraField(new SizeExtraField(message.getFullContentOctets())); + archiveEntry.addExtraField(new UidExtraField(message.getUid().asLong())); + archiveEntry.addExtraField(new MessageIdExtraField(message.getMessageId().serialize())); + archiveEntry.addExtraField(new MailboxIdExtraField(message.getMailboxId().serialize())); + archiveOutputStream.putArchiveEntry(archiveEntry); IOUtils.copy(message.getFullContent(), archiveOutputStream); archiveOutputStream.closeArchiveEntry(); http://git-wip-us.apache.org/repos/asf/james-project/blob/f30001c2/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxIdExtraFieldTest.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxIdExtraFieldTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxIdExtraFieldTest.java new file mode 100644 index 0000000..684f20c --- /dev/null +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxIdExtraFieldTest.java @@ -0,0 +1,207 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 org.apache.james.mailbox.backup; + +import static org.apache.commons.lang3.StringUtils.EMPTY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import com.google.common.base.Charsets; + +public class MailboxIdExtraFieldTest { + + private static final String DEFAULT_MAILBOX_ID = "123456789ABCDEF0"; + private static final byte[] DEFAULT_MAILBOX_ID_BYTE_ARRAY = new byte[] {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30}; + private static final byte [] EMPTY_BYTE_ARRAY = {}; + + @Nested + class GetHeaderId { + + @Test + void getHeaderIdShouldReturnSpecificStringInLittleEndian() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + ByteBuffer byteBuffer = ByteBuffer.wrap(testee.getHeaderId().getBytes()) + .order(ByteOrder.LITTLE_ENDIAN); + + assertThat(Charsets.US_ASCII.decode(byteBuffer).toString()) + .isEqualTo("am"); + } + } + + @Nested + class GetLocalFileDataLength { + + @Test + void getLocalFileDataLengthShouldThrowWhenNoValue() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + assertThatThrownBy(() -> testee.getLocalFileDataLength().getValue()) + .isInstanceOf(RuntimeException.class); + } + + @Test + void getLocalFileDataLengthShouldReturnIntegerSize() { + MailboxIdExtraField testee = new MailboxIdExtraField(DEFAULT_MAILBOX_ID); + + assertThat(testee.getLocalFileDataLength().getValue()) + .isEqualTo(16); + } + } + + @Nested + class GetCentralDirectoryLength { + + @Test + void getCentralDirectoryLengthShouldThrowWhenNoValue() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + assertThatThrownBy(() -> testee.getCentralDirectoryLength().getValue()) + .isInstanceOf(RuntimeException.class); + } + + @Test + void getCentralDirectoryLengthShouldReturnIntegerSize() { + MailboxIdExtraField testee = new MailboxIdExtraField(DEFAULT_MAILBOX_ID); + + assertThat(testee.getCentralDirectoryLength().getValue()) + .isEqualTo(16); + } + } + + @Nested + class GetLocalFileDataData { + + @Test + void getLocalFileDataDataShouldThrowWhenNoValue() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + + assertThatThrownBy(() -> testee.getLocalFileDataData()) + .isInstanceOf(RuntimeException.class); + } + + @Test + void getLocalFileDataDataShouldReturnEmptyArrayWhenValueIsEmpty() { + byte[] actual = new MailboxIdExtraField(EMPTY).getLocalFileDataData(); + assertThat(actual).isEqualTo(EMPTY_BYTE_ARRAY); + } + + @Test + void getLocalFileDataDataShouldReturnValueInByteArray() { + byte[] actual = new MailboxIdExtraField(DEFAULT_MAILBOX_ID).getLocalFileDataData(); + assertThat(actual).isEqualTo(DEFAULT_MAILBOX_ID_BYTE_ARRAY); + } + } + + @Nested + class GetCentralDirectoryData { + + @Test + void getCentralDirectoryDataShouldThrowWhenNoValue() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + + assertThatThrownBy(() -> testee.getCentralDirectoryData()) + .isInstanceOf(RuntimeException.class); + } + + @Test + void getCentralDirectoryDataShouldReturnEmptyArrayWhenValueIsEmpty() { + byte[] actual = new MailboxIdExtraField(EMPTY).getCentralDirectoryData(); + assertThat(actual).isEqualTo(EMPTY_BYTE_ARRAY); + } + + @Test + void getCentralDirectoryDataShouldReturnValueInByteArray() { + byte[] actual = new MailboxIdExtraField(DEFAULT_MAILBOX_ID).getCentralDirectoryData(); + assertThat(actual).isEqualTo(DEFAULT_MAILBOX_ID_BYTE_ARRAY); + } + } + + @Nested + class ParseFromLocalFileData { + + @Test + void parseFromLocalFileDataShouldParseWhenZero() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + + testee.parseFromLocalFileData(EMPTY_BYTE_ARRAY, 0, 0); + + assertThat(testee.getMailboxId()) + .contains(EMPTY); + } + + @Test + void parseFromLocalFileDataShouldParseByteArray() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + + testee.parseFromLocalFileData(DEFAULT_MAILBOX_ID_BYTE_ARRAY, 0, 16); + + assertThat(testee.getMailboxId()) + .contains(DEFAULT_MAILBOX_ID); + } + + @Test + void parseFromLocalFileDataShouldHandleOffset() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + + testee.parseFromLocalFileData(DEFAULT_MAILBOX_ID_BYTE_ARRAY, 2, 14); + + assertThat(testee.getMailboxId()) + .contains("3456789ABCDEF0"); + } + } + + @Nested + class ParseFromCentralDirectoryData { + + @Test + void parseFromCentralDirectoryDataShouldParseWhenZero() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + + testee.parseFromCentralDirectoryData(EMPTY_BYTE_ARRAY, 0, 0); + + assertThat(testee.getMailboxId()) + .contains(EMPTY); + } + + @Test + void parseFromCentralDirectoryDataShouldParseByteArray() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + + testee.parseFromCentralDirectoryData(DEFAULT_MAILBOX_ID_BYTE_ARRAY, 0, 16); + + assertThat(testee.getMailboxId()) + .contains(DEFAULT_MAILBOX_ID); + } + + @Test + void parseFromCentralDirectoryDataShouldHandleOffset() { + MailboxIdExtraField testee = new MailboxIdExtraField(); + + testee.parseFromCentralDirectoryData(DEFAULT_MAILBOX_ID_BYTE_ARRAY, 2, 14); + + assertThat(testee.getMailboxId()) + .contains("3456789ABCDEF0"); + } + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/f30001c2/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java index ea4b027..92ff524 100644 --- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MailboxMessageFixture.java @@ -30,6 +30,8 @@ import javax.mail.util.SharedByteArrayInputStream; import org.apache.james.mailbox.MailboxSession; import org.apache.james.mailbox.mock.MockMailboxSession; import org.apache.james.mailbox.model.MailboxPath; +import org.apache.james.mailbox.MessageUid; +import org.apache.james.mailbox.model.MailboxId; import org.apache.james.mailbox.model.MessageId; import org.apache.james.mailbox.model.TestId; import org.apache.james.mailbox.model.TestMessageId; @@ -53,6 +55,11 @@ public interface MailboxMessageFixture { MessageId MESSAGE_ID_2 = MESSAGE_ID_FACTORY.generate(); long SIZE_1 = 1000; long SIZE_2 = 2000; + long MESSAGE_UID_1_VALUE = 1111L; + long MESSAGE_UID_2_VALUE = 2222L; + MessageUid MESSAGE_UID_1 = MessageUid.of(MESSAGE_UID_1_VALUE); + MessageUid MESSAGE_UID_2 = MessageUid.of(MESSAGE_UID_2_VALUE); + MailboxId MAILBOX_ID_1 = TestId.of(1L); MailboxSession MAILBOX_SESSION = new MockMailboxSession("user"); @@ -62,23 +69,25 @@ public interface MailboxMessageFixture { SimpleMailboxMessage MESSAGE_1 = SimpleMailboxMessage.builder() .messageId(MESSAGE_ID_1) + .uid(MESSAGE_UID_1) .content(CONTENT_STREAM_1) .size(SIZE_1) .internalDate(new Date(DATE_1.toEpochSecond())) .bodyStartOctet(0) .flags(new Flags()) .propertyBuilder(new PropertyBuilder()) - .mailboxId(TestId.of(1L)) + .mailboxId(MAILBOX_ID_1) .build(); SimpleMailboxMessage MESSAGE_2 = SimpleMailboxMessage.builder() .messageId(MESSAGE_ID_2) + .uid(MESSAGE_UID_2) .content(CONTENT_STREAM_2) .size(SIZE_2) .internalDate(new Date(DATE_2.toEpochSecond())) .bodyStartOctet(0) .flags(new Flags()) .propertyBuilder(new PropertyBuilder()) - .mailboxId(TestId.of(1L)) + .mailboxId(MAILBOX_ID_1) .build(); } http://git-wip-us.apache.org/repos/asf/james-project/blob/f30001c2/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MessageIdExtraFieldTest.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MessageIdExtraFieldTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MessageIdExtraFieldTest.java new file mode 100644 index 0000000..9aa8698 --- /dev/null +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/MessageIdExtraFieldTest.java @@ -0,0 +1,214 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 org.apache.james.mailbox.backup; + +import static org.apache.commons.lang3.StringUtils.EMPTY; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import com.google.common.base.Charsets; + +public class MessageIdExtraFieldTest { + + private static final String DEFAULT_MESSAGE_ID = "123456789ABCDEF0"; + private static final byte[] DEFAULT_MESSAGE_ID_BYTE_ARRAY = new byte[] {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x30}; + private static final byte [] EMPTY_BYTE_ARRAY = {}; + + @Nested + class GetHeaderId { + + @Test + void getHeaderIdShouldReturnSpecificStringInLittleEndian() { + MessageIdExtraField testee = new MessageIdExtraField(); + ByteBuffer byteBuffer = ByteBuffer.wrap(testee.getHeaderId().getBytes()) + .order(ByteOrder.LITTLE_ENDIAN); + + assertThat(Charsets.US_ASCII.decode(byteBuffer).toString()) + .isEqualTo("al"); + } + } + + @Nested + class GetLocalFileDataLength { + + @Test + void getLocalFileDataLengthShouldThrowWhenNoValue() { + MessageIdExtraField testee = new MessageIdExtraField(); + + assertThatThrownBy(() -> testee.getLocalFileDataLength().getValue()) + .isInstanceOf(RuntimeException.class); + } + + @Test + void getLocalFileDataLengthShouldReturnIntegerSize() { + MessageIdExtraField testee = new MessageIdExtraField(DEFAULT_MESSAGE_ID); + + assertThat(testee.getLocalFileDataLength().getValue()) + .isEqualTo(16); + } + } + + @Nested + class GetCentralDirectoryLength { + + @Test + void getCentralDirectoryLengthShouldThrowWhenNoValue() { + MessageIdExtraField testee = new MessageIdExtraField(); + + assertThatThrownBy(() -> testee.getCentralDirectoryLength().getValue()) + .isInstanceOf(RuntimeException.class); + } + + @Test + void getCentralDirectoryLengthShouldReturnIntegerSize() { + MessageIdExtraField testee = new MessageIdExtraField(DEFAULT_MESSAGE_ID); + + assertThat(testee.getCentralDirectoryLength().getValue()) + .isEqualTo(16); + } + } + + @Nested + class GetLocalFileDataData { + + @Test + void getLocalFileDataDataShouldThrowWhenNoValue() { + MessageIdExtraField testee = new MessageIdExtraField(); + + assertThatThrownBy(() -> testee.getLocalFileDataData()) + .isInstanceOf(RuntimeException.class); + } + + @Test + void getLocalFileDataDataShouldReturnEmptyArrayWhenValueIsEmpty() { + MessageIdExtraField testee = new MessageIdExtraField(); + byte[] actual = new MessageIdExtraField(EMPTY).getLocalFileDataData(); + + assertThat(actual).isEqualTo(EMPTY_BYTE_ARRAY); + } + + @Test + void getLocalFileDataDataShouldReturnValueInByteArray() { + MessageIdExtraField testee = new MessageIdExtraField(); + byte[] actual = new MessageIdExtraField(DEFAULT_MESSAGE_ID).getLocalFileDataData(); + + assertThat(actual).isEqualTo(DEFAULT_MESSAGE_ID_BYTE_ARRAY); + } + } + + @Nested + class GetCentralDirectoryData { + + @Test + void getCentralDirectoryDataShouldThrowWhenNoValue() { + MessageIdExtraField testee = new MessageIdExtraField(); + + assertThatThrownBy(() -> testee.getCentralDirectoryData()) + .isInstanceOf(RuntimeException.class); + } + + @Test + void getCentralDirectoryDataShouldReturnEmptyArrayWhenValueIsEmpty() { + byte[] actual = new MessageIdExtraField(EMPTY).getCentralDirectoryData(); + assertThat(actual).isEqualTo(EMPTY_BYTE_ARRAY); + } + + @Test + void getCentralDirectoryDataShouldReturnValueInByteArray() { + byte[] actual = new MessageIdExtraField(DEFAULT_MESSAGE_ID).getCentralDirectoryData(); + assertThat(actual).isEqualTo(DEFAULT_MESSAGE_ID_BYTE_ARRAY); + } + } + + @Nested + class ParseFromLocalFileData { + + @Test + void parseFromLocalFileDataShouldParseWhenZero() { + MessageIdExtraField testee = new MessageIdExtraField(); + + testee.parseFromLocalFileData(EMPTY_BYTE_ARRAY, 0, 0); + + assertThat(testee.getMessageId()) + .contains(EMPTY); + } + + @Test + void parseFromLocalFileDataShouldParseByteArray() { + MessageIdExtraField testee = new MessageIdExtraField(); + + testee.parseFromLocalFileData(DEFAULT_MESSAGE_ID_BYTE_ARRAY, 0, 16); + + assertThat(testee.getMessageId()) + .contains(DEFAULT_MESSAGE_ID); + } + + @Test + void parseFromLocalFileDataShouldHandleOffset() { + MessageIdExtraField testee = new MessageIdExtraField(); + + testee.parseFromLocalFileData(DEFAULT_MESSAGE_ID_BYTE_ARRAY, 2, 14); + + assertThat(testee.getMessageId()) + .contains("3456789ABCDEF0"); + } + } + + @Nested + class ParseFromCentralDirectoryData { + + @Test + void parseFromCentralDirectoryDataShouldParseWhenZero() { + MessageIdExtraField testee = new MessageIdExtraField(); + + testee.parseFromCentralDirectoryData(EMPTY_BYTE_ARRAY, 0, 0); + + assertThat(testee.getMessageId()) + .contains(EMPTY); + } + + @Test + void parseFromCentralDirectoryDataShouldParseByteArray() { + MessageIdExtraField testee = new MessageIdExtraField(); + + testee.parseFromCentralDirectoryData(DEFAULT_MESSAGE_ID_BYTE_ARRAY, 0, 16); + + assertThat(testee.getMessageId()) + .contains(DEFAULT_MESSAGE_ID); + } + + @Test + void parseFromCentralDirectoryDataShouldHandleOffset() { + MessageIdExtraField testee = new MessageIdExtraField(); + + testee.parseFromCentralDirectoryData(DEFAULT_MESSAGE_ID_BYTE_ARRAY, 2, 14); + + assertThat(testee.getMessageId()) + .contains("3456789ABCDEF0"); + } + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/f30001c2/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/UidExtraFieldTest.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/UidExtraFieldTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/UidExtraFieldTest.java new file mode 100644 index 0000000..b920ec5 --- /dev/null +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/UidExtraFieldTest.java @@ -0,0 +1,254 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you 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 org.apache.james.mailbox.backup; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.zip.ZipException; + +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; +import org.testcontainers.shaded.org.bouncycastle.util.Arrays; + +import com.google.common.base.Charsets; + +public class UidExtraFieldTest { + private static final byte[] ZERO_AS_BYTE_ARRAY = {0, 0, 0, 0, 0, 0, 0, 0}; + private static final byte[] _123456789ABCDEF0_AS_LE_BYTE_ARRAY = new byte[] {(byte) 0xF0, (byte) 0xDE, (byte) 0xBC, (byte) 0x9A, 0x78, 0x56, 0x34, 0x12}; + private static final byte[] FEDCBA9876543210_AS_LE_BYTE_ARRAY = new byte[] {0x10, 0x32, 0x54, 0x76, (byte) 0x98, (byte) 0xBA, (byte) 0xDC, (byte) 0xFE}; + private static final byte[] UNUSED = new byte[] {(byte) 0xDE, (byte) 0xAD}; + + @Nested + class GetHeaderId { + + @Test + void getHeaderIdShouldReturnSpecificStringInLittleEndian() { + UidExtraField testee = new UidExtraField(); + + ByteBuffer byteBuffer = ByteBuffer.wrap(testee.getHeaderId().getBytes()) + .order(ByteOrder.LITTLE_ENDIAN); + assertThat(Charsets.US_ASCII.decode(byteBuffer).toString()) + .isEqualTo("ak"); + } + } + + @Nested + class GetLocalFileDataLength { + @Test + void getLocalFileDataLengthShouldReturnIntegerSize() { + UidExtraField testee = new UidExtraField(); + + assertThat(testee.getLocalFileDataLength().getValue()) + .isEqualTo(Long.BYTES); + } + } + + @Nested + class GetCentralDirectoryLength { + + @Test + void getCentralDirectoryLengthShouldReturnIntegerSize() { + UidExtraField testee = new UidExtraField(); + + assertThat(testee.getCentralDirectoryLength().getValue()) + .isEqualTo(Long.BYTES); + } + + + @Test + void getCentralDirectoryDataShouldThrowWhenNoValue() { + UidExtraField testee = new UidExtraField(); + + assertThatThrownBy(() -> testee.getCentralDirectoryData()) + .isInstanceOf(RuntimeException.class); + } + + @Test + void getCentralDirectoryDataShouldReturnZeroWhenZero() { + byte[] actual = new UidExtraField(0).getCentralDirectoryData(); + assertThat(actual).isEqualTo(ZERO_AS_BYTE_ARRAY); + } + + @Test + void getCentralDirectoryDataShouldReturnValueInLittleIndianWhen123456789ABCDEF0() { + byte[] actual = new UidExtraField(0x123456789ABCDEF0L).getCentralDirectoryData(); + assertThat(actual).isEqualTo(_123456789ABCDEF0_AS_LE_BYTE_ARRAY); + } + + @Test + void getCentralDirectoryDataShouldReturnValueInLittleIndianWhenFEDCBA9876543210() { + byte[] actual = new UidExtraField(0xFEDCBA9876543210L).getCentralDirectoryData(); + assertThat(actual).isEqualTo(FEDCBA9876543210_AS_LE_BYTE_ARRAY); + } + } + + @Nested + class GetLocalFileDataData { + + @Test + void getLocalFileDataDataShouldThrowWhenNoValue() { + UidExtraField testee = new UidExtraField(); + + assertThatThrownBy(() -> testee.getLocalFileDataData()) + .isInstanceOf(RuntimeException.class); + } + + @Test + void getLocalFileDataDataShouldReturnZeroWhenZero() { + byte[] actual = new UidExtraField(0).getLocalFileDataData(); + assertThat(actual).isEqualTo(ZERO_AS_BYTE_ARRAY); + } + + @Test + void getLocalFileDataDataShouldReturnValueInLittleIndianWhen123456789ABCDEF0() { + byte[] actual = new UidExtraField(0x123456789ABCDEF0L).getLocalFileDataData(); + assertThat(actual).isEqualTo(_123456789ABCDEF0_AS_LE_BYTE_ARRAY); + } + + @Test + void getLocalFileDataDataShouldReturnValueInLittleIndianWhenFEDCBA9876543210() { + byte[] actual = new UidExtraField(0xFEDCBA9876543210L).getLocalFileDataData(); + assertThat(actual).isEqualTo(FEDCBA9876543210_AS_LE_BYTE_ARRAY); + } + } + + @Nested + class ParseFromLocalFileData { + + @Test + void parseFromLocalFileDataShouldThrownWhenLengthIsSmallerThan8() { + UidExtraField testee = new UidExtraField(); + + byte[] input = new byte[] {0, 0, 0, 0, 0, 0, 0}; + assertThatThrownBy(() -> testee.parseFromLocalFileData(input, 0, 7)) + .isInstanceOf(ZipException.class); + } + + @Test + void parseFromLocalFileDataShouldThrownWhenLengthIsBiggerThan8() { + UidExtraField testee = new UidExtraField(); + + byte[] input = new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0}; + assertThatThrownBy(() -> testee.parseFromLocalFileData(input, 0, 9)) + .isInstanceOf(ZipException.class); + } + + @Test + void parseFromLocalFileDataShouldParseWhenZero() throws Exception { + UidExtraField testee = new UidExtraField(); + + testee.parseFromLocalFileData(ZERO_AS_BYTE_ARRAY, 0, 8); + assertThat(testee.getUid()) + .contains(0L); + } + + @Test + void parseFromLocalFileDataShouldParseWhen123456789ABCDEF0InLittleEndian() throws Exception { + UidExtraField testee = new UidExtraField(); + + testee.parseFromLocalFileData(_123456789ABCDEF0_AS_LE_BYTE_ARRAY, 0, 8); + assertThat(testee.getUid()) + .contains(0x123456789ABCDEF0L); + } + + @Test + void parseFromLocalFileDataShouldParseWhenFEDCBA9876543210InLittleEndian() throws Exception { + UidExtraField testee = new UidExtraField(); + + byte[] input = FEDCBA9876543210_AS_LE_BYTE_ARRAY; + testee.parseFromLocalFileData(input, 0, 8); + assertThat(testee.getUid()) + .contains(0xFEDCBA9876543210L); + } + + @Test + void parseFromLocalFileDataShouldHandleOffset() throws Exception { + UidExtraField testee = new UidExtraField(); + + byte[] input = Arrays.concatenate(UNUSED, _123456789ABCDEF0_AS_LE_BYTE_ARRAY); + testee.parseFromLocalFileData(input, 2, 8); + assertThat(testee.getUid()) + .contains(0x123456789ABCDEF0L); + } + } + + @Nested + class ParseFromCentralDirectoryData { + + @Test + void parseFromCentralDirectoryDataShouldThrownWhenLengthIsSmallerThan8() { + UidExtraField testee = new UidExtraField(); + byte[] input = new byte[7]; + + assertThatThrownBy(() -> testee.parseFromCentralDirectoryData(input, 0, 7)) + .isInstanceOf(ZipException.class); + } + + @Test + void parseFromCentralDirectoryDataShouldThrownWhenLengthIsBiggerThan8() { + UidExtraField testee = new UidExtraField(); + byte[] input = new byte[9]; + + assertThatThrownBy(() -> testee.parseFromCentralDirectoryData(input, 0, 9)) + .isInstanceOf(ZipException.class); + } + + @Test + void parseFromCentralDirectoryDataShouldParseWhenZero() throws Exception { + UidExtraField testee = new UidExtraField(); + + testee.parseFromCentralDirectoryData(ZERO_AS_BYTE_ARRAY, 0, 8); + assertThat(testee.getUid()) + .contains(0L); + } + + @Test + void parseFromCentralDirectoryDataShouldParseWhen123456789ABCDEF0InLittleEndian() throws Exception { + UidExtraField testee = new UidExtraField(); + + testee.parseFromCentralDirectoryData(_123456789ABCDEF0_AS_LE_BYTE_ARRAY, 0, 8); + assertThat(testee.getUid()) + .contains(0x123456789ABCDEF0L); + } + + @Test + void parseFromCentralDirectoryDataShouldParseWhenFEDCBA9876543210InLittleEndian() throws Exception { + UidExtraField testee = new UidExtraField(); + byte[] input = FEDCBA9876543210_AS_LE_BYTE_ARRAY; + + testee.parseFromCentralDirectoryData(input, 0, 8); + assertThat(testee.getUid()) + .contains(0xFEDCBA9876543210L); + } + + @Test + void parseFromCentralDirectoryDataShouldHandleOffset() throws Exception { + UidExtraField testee = new UidExtraField(); + byte[] input = Arrays.concatenate(UNUSED, _123456789ABCDEF0_AS_LE_BYTE_ARRAY); + + testee.parseFromCentralDirectoryData(input, 2, 8); + assertThat(testee.getUid()) + .contains(0x123456789ABCDEF0L); + } + } +} http://git-wip-us.apache.org/repos/asf/james-project/blob/f30001c2/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java ---------------------------------------------------------------------- diff --git a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java index d11c8c5..6e67a91 100644 --- a/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java +++ b/mailbox/backup/src/test/java/org/apache/james/mailbox/backup/ZipperTest.java @@ -21,12 +21,14 @@ package org.apache.james.mailbox.backup; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MAILBOX_1; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MAILBOX_1_SUB_1; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MAILBOX_2; +import static org.apache.james.mailbox.backup.MailboxMessageFixture.MAILBOX_ID_1; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_1; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_2; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_CONTENT_1; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_CONTENT_2; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_ID_1; import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_ID_2; +import static org.apache.james.mailbox.backup.MailboxMessageFixture.MESSAGE_UID_1_VALUE; import static org.apache.james.mailbox.backup.MailboxMessageFixture.SIZE_1; import static org.apache.james.mailbox.backup.ZipAssert.assertThatZip; import static org.apache.james.mailbox.backup.ZipAssert.EntryChecks.hasName; @@ -89,14 +91,17 @@ class ZipperTest { } @Test - void archiveShouldWriteSizeMetadata() throws Exception { + void archiveShouldWriteMetadata() throws Exception { testee.archive(NO_MAILBOXES, Stream.of(MESSAGE_1), output); try (ZipFile zipFile = new ZipFile(toSeekableByteChannel(output))) { assertThatZip(zipFile) .containsOnlyEntriesMatching( hasName(MESSAGE_ID_1.serialize()) - .containsExtraFields(new SizeExtraField(SIZE_1))); + .containsExtraFields(new SizeExtraField(SIZE_1)) + .containsExtraFields(new UidExtraField(MESSAGE_UID_1_VALUE)) + .containsExtraFields(new MessageIdExtraField(MESSAGE_ID_1.serialize())) + .containsExtraFields(new MailboxIdExtraField(MAILBOX_ID_1.serialize()))); } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
