You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by rc...@apache.org on 2019/11/25 02:19:28 UTC

[james-project] branch master updated (26573d1 -> 31fe9b0)

This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git.


    from 26573d1  Merge remote-tracking branch 'benoit/JAMES-2937-ops'
     new d33b22c  [BugFix] port out of range issue in HeadersToHttpTest class
     new 7840311  Fix logging for already created ElasticSearch index
     new 3d8fdf5  JAMES-2904 Improve Mailbox Reindexing efficiency
     new f1ca51e  JAMES-2904 MessageResult::hasAttachment
     new 1259c20  JAMES-2904 MessageResult s/getAttachments/getLoadedAttachments
     new 812ea66  JAMES-2949 Username strong typing in IMAP Authentication
     new b73348c  JAMES-2989 Preview POJO
     new 572f25d  JAMES-2989 MessagePreviewStore + memory implementation
     new 6b2a542  JAMES-2988 MessagePropertiesTest migration to Junit 5
     new 31fe9b0  JAMES-2988 Deduce read levels from MessageProperties

The 10 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../james/backends/es/IndexCreationFactory.java    |   2 +-
 .../org/apache/james/backends/es/IndexName.java    |   9 +
 .../apache/james/mailbox/model/MessageResult.java  |  14 +-
 .../apache/james/mailbox/MailboxManagerTest.java   |  45 ++
 .../src/test/resources/eml/twoAttachmentsApi.eml   |  13 +-
 .../cassandra/mail/CassandraMessageDAO.java        |  21 +-
 .../cassandra/mail/MessageWithoutAttachment.java   |   7 +-
 .../cassandra/table/CassandraMessageV2Table.java   |   4 +-
 .../model/openjpa/AbstractJPAMailboxMessage.java   |   5 +
 .../mailbox/maildir/mail/model/MaildirMessage.java |   5 +
 .../james/mailbox/store/MessageResultImpl.java     |   9 +-
 .../mailbox/store/StoreMessageResultIterator.java  |   9 +-
 .../store/mail/model/DelegatingMailboxMessage.java |   5 +
 .../james/mailbox/store/mail/model/Message.java    |   2 +
 .../mail/model/impl/SimpleMailboxMessage.java      |  31 +-
 .../store/mail/model/impl/SimpleMessage.java       |   9 +-
 .../store/AbstractMessageIdManagerStorageTest.java |  31 ++
 .../mailbox/store/MessageIdManagerTestSystem.java  |   3 +
 .../mailbox/tools/indexer/ReIndexerPerformer.java  |   3 +-
 .../james/transport/mailets/HeadersToHTTPTest.java | 452 ++++++++++-----------
 .../imap/decode/parser/LoginCommandParser.java     |   5 +-
 .../james/imap/message/request/LoginRequest.java   |   7 +-
 .../imap/processor/AbstractAuthProcessor.java      |  20 +-
 .../imap/processor/AuthenticateProcessor.java      |   5 +-
 .../apache/james/jmap/draft/MessageIdProbe.java    |   2 +-
 server/data/data-jmap/pom.xml                      |  10 +
 .../jmap/api/preview/MessagePreviewStore.java      |  13 +-
 .../apache/james/jmap/api/preview/Preview.java}    |  32 +-
 .../memory/preview/MemoryMessagePreviewStore.java} |  51 ++-
 .../api/preview/MessagePreviewStoreContract.java   | 168 ++++++++
 .../apache/james/jmap/api/preview/PreviewTest.java |  51 ++-
 .../preview/MemoryMessagePreviewStoreTest.java}    |  18 +-
 .../jmap/draft/methods/GetMessagesMethod.java      |   1 +
 .../james/jmap/draft/model/MessageFactory.java     |   2 +-
 .../james/jmap/draft/model/MessageProperties.java  | 109 +++--
 .../jmap/draft/model/MessagePropertiesTest.java    | 114 +++++-
 36 files changed, 882 insertions(+), 405 deletions(-)
 copy server/protocols/jmap-draft-integration-testing/jmap-draft-integration-testing-common/src/test/resources/eml/twoAttachmentsTextPlain.eml => mailbox/api/src/test/resources/eml/twoAttachmentsApi.eml (84%)
 copy mailbox/api/src/main/java/org/apache/james/mailbox/indexer/MessageIdReIndexer.java => server/data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/MessagePreviewStore.java (81%)
 copy server/{mailrepository/mailrepository-api/src/main/java/org/apache/james/mailrepository/api/Protocol.java => data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/Preview.java} (72%)
 copy server/{protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/send/MailMetadata.java => data/data-jmap/src/main/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStore.java} (54%)
 create mode 100644 server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/MessagePreviewStoreContract.java
 copy mailbox/api/src/test/java/org/apache/james/mailbox/model/search/ExactNameTest.java => server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/PreviewTest.java (57%)
 copy server/{mailrepository/mailrepository-memory/src/test/java/org/apache/james/mailrepository/memory/MemoryMailRepositoryTest.java => data/data-jmap/src/test/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStoreTest.java} (73%)


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 07/10: JAMES-2989 Preview POJO

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit b73348ca0d22431477625358ff916601066dafcf
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Thu Nov 21 17:08:25 2019 +0700

    JAMES-2989 Preview POJO
    
    The model is used in MessagePreviewStore, representing message previews
    of JMAP getMessages responses
---
 .../org/apache/james/jmap/api/preview/Preview.java | 64 +++++++++++++++++++
 .../apache/james/jmap/api/preview/PreviewTest.java | 73 ++++++++++++++++++++++
 2 files changed, 137 insertions(+)

diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/Preview.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/Preview.java
new file mode 100644
index 0000000..0d4a208
--- /dev/null
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/Preview.java
@@ -0,0 +1,64 @@
+/****************************************************************
+ * 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.jmap.api.preview;
+
+import java.util.Objects;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Preconditions;
+
+public class Preview {
+
+    private static final int MAX_LENGTH = 256;
+
+    public static Preview from(String value) {
+        return new Preview(value);
+    }
+
+    private final String value;
+
+    @VisibleForTesting
+    Preview(String value) {
+        Preconditions.checkNotNull(value);
+        Preconditions.checkArgument(value.length() <= MAX_LENGTH,
+            String.format("the preview value '%s' has length longer than %d", value, MAX_LENGTH));
+
+        this.value = value;
+    }
+
+    public String getValue() {
+        return value;
+    }
+
+    @Override
+    public final boolean equals(Object o) {
+        if (o instanceof Preview) {
+            Preview preview = (Preview) o;
+
+            return Objects.equals(this.value, preview.value);
+        }
+        return false;
+    }
+
+    @Override
+    public final int hashCode() {
+        return Objects.hash(value);
+    }
+}
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/PreviewTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/PreviewTest.java
new file mode 100644
index 0000000..8298f5d
--- /dev/null
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/PreviewTest.java
@@ -0,0 +1,73 @@
+/****************************************************************
+ * 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.jmap.api.preview;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.junit.jupiter.api.Test;
+
+import com.google.common.base.Strings;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+
+class PreviewTest {
+
+    private static final String PREVIEW_RAW_VALUE = "Hello James!";
+
+    @Test
+    void shouldMatchBeanContract() {
+        EqualsVerifier.forClass(Preview.class)
+            .verify();
+    }
+
+    @Test
+    void getValueShouldReturnCorrectPreviewString() {
+        assertThat(new Preview(PREVIEW_RAW_VALUE).getValue())
+            .isEqualTo(PREVIEW_RAW_VALUE);
+    }
+
+    @Test
+    void fromShouldReturnACorrectPreview() {
+        assertThat(Preview.from(PREVIEW_RAW_VALUE))
+            .isEqualTo(new Preview(PREVIEW_RAW_VALUE));
+    }
+
+    @Test
+    void fromShouldThrowWhenNullValue() {
+        assertThatThrownBy(() -> Preview.from(null))
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    void fromShouldThrowWhenValueLengthIsLongerThanMaximum256() {
+        String errorMessageRegex = "the preview value '.*' has length longer than 256";
+        assertThatThrownBy(() -> Preview.from(Strings.repeat("a", 257)))
+            .isInstanceOf(IllegalArgumentException.class)
+            .hasMessageMatching(errorMessageRegex);
+    }
+
+    @Test
+    void fromShouldNotThrowWhenValueLengthIsEqualsToMaximum256() {
+        assertThatCode(() -> Preview.from(Strings.repeat("a", 256)))
+            .doesNotThrowAnyException();
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 08/10: JAMES-2989 MessagePreviewStore + memory implementation

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 572f25d41b914ac1c14c4b02c2b72d3d49911743
Author: Tran Tien Duc <dt...@linagora.com>
AuthorDate: Thu Nov 21 17:09:00 2019 +0700

    JAMES-2989 MessagePreviewStore + memory implementation
---
 server/data/data-jmap/pom.xml                      |  10 ++
 .../jmap/api/preview/MessagePreviewStore.java      |  32 ++++
 .../memory/preview/MemoryMessagePreviewStore.java  |  62 ++++++++
 .../api/preview/MessagePreviewStoreContract.java   | 168 +++++++++++++++++++++
 .../preview/MemoryMessagePreviewStoreTest.java     |  39 +++++
 5 files changed, 311 insertions(+)

diff --git a/server/data/data-jmap/pom.xml b/server/data/data-jmap/pom.xml
index 249ae81..3626162 100644
--- a/server/data/data-jmap/pom.xml
+++ b/server/data/data-jmap/pom.xml
@@ -35,6 +35,16 @@
     <dependencies>
         <dependency>
             <groupId>${james.groupId}</groupId>
+            <artifactId>apache-james-mailbox-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
+            <artifactId>apache-james-mailbox-api</artifactId>
+            <scope>test</scope>
+            <type>test-jar</type>
+        </dependency>
+        <dependency>
+            <groupId>${james.groupId}</groupId>
             <artifactId>james-core</artifactId>
         </dependency>
         <dependency>
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/MessagePreviewStore.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/MessagePreviewStore.java
new file mode 100644
index 0000000..c772b80
--- /dev/null
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/api/preview/MessagePreviewStore.java
@@ -0,0 +1,32 @@
+/****************************************************************
+ * 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.jmap.api.preview;
+
+import org.apache.james.mailbox.model.MessageId;
+import org.reactivestreams.Publisher;
+
+public interface MessagePreviewStore {
+
+    Publisher<Void> store(MessageId messageId, Preview preview);
+
+    Publisher<Preview> retrieve(MessageId messageId);
+
+    Publisher<Void> delete(MessageId messageId);
+}
diff --git a/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStore.java b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStore.java
new file mode 100644
index 0000000..58bf9c4
--- /dev/null
+++ b/server/data/data-jmap/src/main/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStore.java
@@ -0,0 +1,62 @@
+/****************************************************************
+ * 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.jmap.memory.preview;
+
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.james.jmap.api.preview.MessagePreviewStore;
+import org.apache.james.jmap.api.preview.Preview;
+import org.apache.james.mailbox.model.MessageId;
+import org.reactivestreams.Publisher;
+
+import com.google.common.base.Preconditions;
+
+import reactor.core.publisher.Mono;
+
+public class MemoryMessagePreviewStore implements MessagePreviewStore {
+
+    private final ConcurrentHashMap<MessageId, Preview> previews;
+
+    public MemoryMessagePreviewStore() {
+        this.previews = new ConcurrentHashMap<>();
+    }
+
+    @Override
+    public Publisher<Void> store(MessageId messageId, Preview preview) {
+        Preconditions.checkNotNull(messageId);
+        Preconditions.checkNotNull(preview);
+
+        return Mono.fromRunnable(() -> previews.put(messageId, preview));
+    }
+
+    @Override
+    public Publisher<Preview> retrieve(MessageId messageId) {
+        Preconditions.checkNotNull(messageId);
+
+        return Mono.fromSupplier(() -> previews.get(messageId));
+    }
+
+    @Override
+    public Publisher<Void> delete(MessageId messageId) {
+        Preconditions.checkNotNull(messageId);
+
+        return Mono.fromRunnable(() -> previews.remove(messageId));
+    }
+}
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/MessagePreviewStoreContract.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/MessagePreviewStoreContract.java
new file mode 100644
index 0000000..3320684
--- /dev/null
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/api/preview/MessagePreviewStoreContract.java
@@ -0,0 +1,168 @@
+/****************************************************************
+ * 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.jmap.api.preview;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.TestMessageId;
+import org.assertj.core.api.SoftAssertions;
+import org.junit.jupiter.api.Test;
+
+import reactor.core.publisher.Mono;
+
+public interface MessagePreviewStoreContract {
+
+    MessageId MESSAGE_ID_1 = TestMessageId.of(1);
+    Preview PREVIEW_1 = Preview.from("message id 1");
+    MessageId MESSAGE_ID_2 = TestMessageId.of(2);
+    Preview PREVIEW_2 = Preview.from("message id 2");
+
+    MessagePreviewStore testee();
+
+    @Test
+    default void retrieveShouldThrowWhenNullMessageId() {
+        assertThatThrownBy(() -> Mono.from(testee().retrieve(null)).block())
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    default void retrieveShouldReturnStoredPreview() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).block())
+            .isEqualTo(PREVIEW_1);
+    }
+
+    @Test
+    default void retrieveShouldReturnEmptyWhenMessageIdNotFound() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_2)).blockOptional())
+            .isEmpty();
+    }
+
+    @Test
+    default void retrieveShouldReturnTheRightPreviewWhenStoringMultipleMessageIds() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+        Mono.from(testee().store(MESSAGE_ID_2, PREVIEW_2))
+            .block();
+
+        SoftAssertions.assertSoftly(softly -> {
+           softly.assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).block())
+               .isEqualTo(PREVIEW_1);
+           softly.assertThat(Mono.from(testee().retrieve(MESSAGE_ID_2)).block())
+               .isEqualTo(PREVIEW_2);
+        });
+    }
+
+    @Test
+    default void storeShouldThrowWhenNullMessageId() {
+        assertThatThrownBy(() -> Mono.from(testee().store(null, PREVIEW_1)).block())
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    default void storeShouldThrowWhenNullPreview() {
+        assertThatThrownBy(() -> Mono.from(testee().store(MESSAGE_ID_1, null)).block())
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    default void storeShouldOverrideOldRecord() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_2))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).block())
+            .isEqualTo(PREVIEW_2);
+    }
+
+    @Test
+    default void storeShouldBeIdempotent() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).block())
+            .isEqualTo(PREVIEW_1);
+    }
+
+    @Test
+    default void deleteShouldThrowWhenNullMessageId() {
+        assertThatThrownBy(() -> Mono.from(testee().delete(null)).block())
+            .isInstanceOf(NullPointerException.class);
+    }
+
+    @Test
+    default void deleteShouldNotThrowWhenMessageIdNotFound() {
+        assertThatCode(() -> Mono.from(testee().delete(MESSAGE_ID_1)).block())
+            .doesNotThrowAnyException();
+    }
+
+    @Test
+    default void deleteShouldDeleteStoredRecord() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        Mono.from(testee().delete(MESSAGE_ID_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).blockOptional())
+            .isEmpty();
+    }
+
+    @Test
+    default void deleteShouldNotDeleteAnotherRecord() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+        Mono.from(testee().store(MESSAGE_ID_2, PREVIEW_2))
+            .block();
+
+        Mono.from(testee().delete(MESSAGE_ID_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_2)).block())
+            .isEqualTo(PREVIEW_2);
+    }
+
+    @Test
+    default void deleteShouldBeIdempotent() {
+        Mono.from(testee().store(MESSAGE_ID_1, PREVIEW_1))
+            .block();
+
+        Mono.from(testee().delete(MESSAGE_ID_1))
+            .block();
+        Mono.from(testee().delete(MESSAGE_ID_1))
+            .block();
+
+        assertThat(Mono.from(testee().retrieve(MESSAGE_ID_1)).blockOptional())
+            .isEmpty();
+    }
+}
\ No newline at end of file
diff --git a/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStoreTest.java b/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStoreTest.java
new file mode 100644
index 0000000..d56c38f
--- /dev/null
+++ b/server/data/data-jmap/src/test/java/org/apache/james/jmap/memory/preview/MemoryMessagePreviewStoreTest.java
@@ -0,0 +1,39 @@
+/****************************************************************
+ * 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.jmap.memory.preview;
+
+import org.apache.james.jmap.api.preview.MessagePreviewStore;
+import org.apache.james.jmap.api.preview.MessagePreviewStoreContract;
+import org.junit.jupiter.api.BeforeEach;
+
+class MemoryMessagePreviewStoreTest implements MessagePreviewStoreContract {
+
+    private MemoryMessagePreviewStore testee;
+
+    @BeforeEach
+    void setUp() {
+        testee = new MemoryMessagePreviewStore();
+    }
+
+    @Override
+    public MessagePreviewStore testee() {
+        return testee;
+    }
+}
\ No newline at end of file


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 10/10: JAMES-2988 Deduce read levels from MessageProperties

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 31fe9b08e2ec0c447149667ccdac2d442cd2c0cb
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Nov 21 15:35:59 2019 +0700

    JAMES-2988 Deduce read levels from MessageProperties
---
 .../jmap/draft/methods/GetMessagesMethod.java      |   1 +
 .../james/jmap/draft/model/MessageProperties.java  | 109 +++++++++++++++------
 .../jmap/draft/model/MessagePropertiesTest.java    |  96 ++++++++++++++++++
 3 files changed, 174 insertions(+), 32 deletions(-)

diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java
index faae6f4..1b414a0 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/methods/GetMessagesMethod.java
@@ -130,6 +130,7 @@ public class GetMessagesMethod implements Method {
         getMessagesRequest.getAccountId().ifPresent((input) -> notImplemented("accountId"));
 
         try {
+            MessageProperties.ReadLevel readLevel = getMessagesRequest.getProperties().computeReadLevel();
             return GetMessagesResponse.builder()
                 .messages(
                     messageIdManager.getMessages(getMessagesRequest.getIds(), FetchGroupImpl.FULL_CONTENT, mailboxSession)
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageProperties.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageProperties.java
index 2bebd95..13d8f9c 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageProperties.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageProperties.java
@@ -71,6 +71,28 @@ public class MessageProperties {
                 .ensureHeadersMessageProperty();
     }
 
+    public ReadLevel computeReadLevel() {
+        Stream<ReadLevel> readLevels = Stream.concat(this.buildOutputMessageProperties()
+                .stream()
+                .map(MessageProperty::getReadLevel),
+            headerPropertiesReadLevel());
+
+        // If `null`, all properties will be fetched (JMAP Draft)
+        // This defer from RFC-8621 behavior (not implemented here)
+        // If omitted, this defaults to: [ "partId", "blobId", "size", "name", "type", "charset", "disposition", "cid",
+        // "language", "location" ]
+        return readLevels.reduce(ReadLevel::combine)
+            .orElse(ReadLevel.Full);
+
+    }
+
+    private Stream<ReadLevel> headerPropertiesReadLevel() {
+        return headersProperties.map(collection ->
+            collection.stream()
+                .map(any -> ReadLevel.Header))
+            .orElse(Stream.of());
+    }
+
     private ImmutableSet<MessageProperty> buildOutputMessageProperties() {
         return this.messageProperties.orElseGet(MessageProperty::allOutputProperties);
     }
@@ -112,57 +134,62 @@ public class MessageProperties {
         return this;
     }
 
-
     private enum PropertyType {
         INPUTONLY,
         INPUTOUTPUT
     }
 
     public enum MessageProperty implements Property {
-        id("id"),
-        blobId("blobId"),
-        threadId("threadId"),
-        mailboxIds("mailboxIds"),
-        inReplyToMessageId("inReplyToMessageId"),
-        isUnread("isUnread"),
-        isFlagged("isFlagged"),
-        isAnswered("isAnswered"),
-        isDraft("isDraft"),
-        isForwarded("isForwarded"),
-        hasAttachment("hasAttachment"),
-        headers("headers"),
-        from("from"),
-        to("to"),
-        cc("cc"),
-        bcc("bcc"),
-        replyTo("replyTo"),
-        subject("subject"),
-        date("date"),
-        size("size"),
-        preview("preview"),
-        textBody("textBody"),
-        htmlBody("htmlBody"),
-        attachments("attachments"),
-        attachedMessages("attachedMessages"),
-        keywords("keywords"),
-        body("body", PropertyType.INPUTONLY);
+        id("id", ReadLevel.Metadata),
+        blobId("blobId", ReadLevel.Metadata),
+        threadId("threadId", ReadLevel.Metadata),
+        mailboxIds("mailboxIds", ReadLevel.Metadata),
+        inReplyToMessageId("inReplyToMessageId", ReadLevel.Header),
+        isUnread("isUnread", ReadLevel.Metadata),
+        isFlagged("isFlagged", ReadLevel.Metadata),
+        isAnswered("isAnswered", ReadLevel.Metadata),
+        isDraft("isDraft", ReadLevel.Metadata),
+        isForwarded("isForwarded", ReadLevel.Metadata),
+        hasAttachment("hasAttachment", ReadLevel.Full),
+        headers("headers", ReadLevel.Header),
+        from("from", ReadLevel.Header),
+        to("to", ReadLevel.Header),
+        cc("cc", ReadLevel.Header),
+        bcc("bcc", ReadLevel.Header),
+        replyTo("replyTo", ReadLevel.Header),
+        subject("subject", ReadLevel.Header),
+        date("date", ReadLevel.Header),
+        size("size", ReadLevel.Metadata),
+        preview("preview", ReadLevel.Full),
+        textBody("textBody", ReadLevel.Full),
+        htmlBody("htmlBody", ReadLevel.Full),
+        attachments("attachments", ReadLevel.Full),
+        attachedMessages("attachedMessages", ReadLevel.Full),
+        keywords("keywords", ReadLevel.Metadata),
+        body("body", PropertyType.INPUTONLY, ReadLevel.Full);
     
         private final String property;
         private final PropertyType type;
+        private final ReadLevel readLevel;
 
-        MessageProperty(String property) {
-            this(property, PropertyType.INPUTOUTPUT);
+        MessageProperty(String property, ReadLevel readLevel) {
+            this(property, PropertyType.INPUTOUTPUT, readLevel);
         }
 
-        MessageProperty(String property, PropertyType type) {
+        MessageProperty(String property, PropertyType type, ReadLevel readLevel) {
             this.property = property;
             this.type = type;
+            this.readLevel = readLevel;
         }
     
         @Override
         public String asFieldName() {
             return property;
         }
+
+        public ReadLevel getReadLevel() {
+            return readLevel;
+        }
     
         public static Stream<MessageProperty> find(String property) {
             Preconditions.checkNotNull(property);
@@ -184,7 +211,25 @@ public class MessageProperties {
             }
         }
     }
-    
+
+    public enum ReadLevel {
+        Metadata(0),
+        Header(1),
+        Full(2);
+
+        static ReadLevel combine(ReadLevel readLevel1, ReadLevel readLevel2) {
+            if (readLevel1.priority > readLevel2.priority) {
+                return readLevel1;
+            }
+            return readLevel2;
+        }
+
+        private final int priority;
+
+        ReadLevel(int priority) {
+            this.priority = priority;
+        }
+    }
 
     public static class HeaderProperty implements Property {
     
diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java
index 78bb1e7..82738b7 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java
@@ -25,6 +25,7 @@ import java.util.Optional;
 
 import org.apache.james.jmap.draft.model.MessageProperties.HeaderProperty;
 import org.apache.james.jmap.draft.model.MessageProperties.MessageProperty;
+import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableSet;
@@ -87,4 +88,99 @@ class MessagePropertiesTest {
             value -> assertThat(value).contains(HeaderProperty.fromFieldName("x-spam-score"))
         );
     }
+
+    @Test
+    void computeReadLevelShouldReturnHeaderWhenOnlyHeaderProperties() {
+        MessageProperties actual = new MessageProperties(
+            Optional.of(ImmutableSet.of("headers.X-Spam-Score"))).toOutputProperties();
+
+        assertThat(actual.computeReadLevel())
+            .isEqualTo(MessageProperties.ReadLevel.Header);
+    }
+
+    @Test
+    void computeReadLevelShouldReturnMetadataWhenOnlyKeywordProperty() {
+        MessageProperties actual = new MessageProperties(
+            Optional.of(ImmutableSet.of("keywords"))).toOutputProperties();
+
+        assertThat(actual.computeReadLevel())
+            .isEqualTo(MessageProperties.ReadLevel.Metadata);
+    }
+
+    @Test
+    void computeReadLevelShouldReturnFullWhenHtmlBodyProperty() {
+        MessageProperties actual = new MessageProperties(
+            Optional.of(ImmutableSet.of("htmlBody"))).toOutputProperties();
+
+        assertThat(actual.computeReadLevel())
+            .isEqualTo(MessageProperties.ReadLevel.Full);
+    }
+
+    @Test
+    void computeReadLevelShouldCombineReadLevels() {
+        MessageProperties actual = new MessageProperties(
+            Optional.of(ImmutableSet.of("headers.X-Spam-Score", "keywords"))).toOutputProperties();
+
+        assertThat(actual.computeReadLevel())
+            .isEqualTo(MessageProperties.ReadLevel.Header);
+    }
+
+    @Nested
+    class ReadLevelTest {
+        @Test
+        void combineShouldReturnMetadataWhenOnlyMetadata() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                    MessageProperties.ReadLevel.Metadata,
+                    MessageProperties.ReadLevel.Metadata))
+                .isEqualTo(MessageProperties.ReadLevel.Metadata);
+        }
+
+        @Test
+        void combineShouldReturnHeaderWhenOnlyHeader() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                    MessageProperties.ReadLevel.Header,
+                    MessageProperties.ReadLevel.Header))
+                .isEqualTo(MessageProperties.ReadLevel.Header);
+        }
+
+        @Test
+        void combineShouldReturnFullWhenOnlyFull() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                    MessageProperties.ReadLevel.Full,
+                    MessageProperties.ReadLevel.Full))
+                .isEqualTo(MessageProperties.ReadLevel.Full);
+        }
+
+        @Test
+        void combineShouldReturnHeaderWhenHeaderAndMetadata() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                MessageProperties.ReadLevel.Metadata,
+                MessageProperties.ReadLevel.Header))
+                .isEqualTo(MessageProperties.ReadLevel.Header);
+        }
+
+        @Test
+        void combineShouldReturnFullWhenFullAndMetadata() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                MessageProperties.ReadLevel.Metadata,
+                MessageProperties.ReadLevel.Full))
+                .isEqualTo(MessageProperties.ReadLevel.Full);
+        }
+
+        @Test
+        void combineShouldReturnFullWhenFullAndHeader() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                MessageProperties.ReadLevel.Header,
+                MessageProperties.ReadLevel.Full))
+                .isEqualTo(MessageProperties.ReadLevel.Full);
+        }
+
+        @Test
+        void combineShouldCommute() {
+            assertThat(MessageProperties.ReadLevel.combine(
+                MessageProperties.ReadLevel.Full,
+                MessageProperties.ReadLevel.Header))
+                .isEqualTo(MessageProperties.ReadLevel.Full);
+        }
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 01/10: [BugFix] port out of range issue in HeadersToHttpTest class

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit d33b22cab9b9969b2f9a598b12437f5fbb375eec
Author: Rene Cordier <rc...@linagora.com>
AuthorDate: Fri Nov 22 17:56:44 2019 +0700

    [BugFix] port out of range issue in HeadersToHttpTest class
    
    When running this test locally, I was getting a "java.lang.IllegalArgumentException: port out of range:123456" exception.
    The port is indeed out of range...
---
 .../james/transport/mailets/HeadersToHTTPTest.java | 452 ++++++++++-----------
 1 file changed, 226 insertions(+), 226 deletions(-)

diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/HeadersToHTTPTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/HeadersToHTTPTest.java
index 9eda16b..c0860fc 100644
--- a/mailet/standard/src/test/java/org/apache/james/transport/mailets/HeadersToHTTPTest.java
+++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/HeadersToHTTPTest.java
@@ -1,226 +1,226 @@
-/****************************************************************
- * 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.transport.mailets;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-import javax.mail.MessagingException;
-
-import org.apache.http.ExceptionLogger;
-import org.apache.http.HttpStatus;
-import org.apache.http.NameValuePair;
-import org.apache.http.client.utils.URLEncodedUtils;
-import org.apache.http.config.SocketConfig;
-import org.apache.http.entity.BasicHttpEntity;
-import org.apache.http.impl.bootstrap.HttpServer;
-import org.apache.http.impl.bootstrap.ServerBootstrap;
-import org.apache.http.message.BasicHttpEntityEnclosingRequest;
-import org.apache.http.protocol.UriHttpRequestHandlerMapper;
-import org.apache.http.util.EntityUtils;
-import org.apache.james.util.MimeMessageUtil;
-import org.apache.mailet.Mail;
-import org.apache.mailet.Mailet;
-import org.apache.mailet.base.test.FakeMailetConfig;
-import org.apache.mailet.base.test.MailUtil;
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-
-class HeadersToHTTPTest {
-
-    private static HttpServer server;
-    private static UriHttpRequestHandlerMapper mapper;
-    private Mail mail;
-
-    private String urlTestPattern;
-
-    @BeforeAll
-    static void setupServer() throws Exception {
-        mapper = new UriHttpRequestHandlerMapper();
-
-        SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(50000).build();
-        server = ServerBootstrap.bootstrap().setListenerPort(0).setSocketConfig(socketConfig)
-                .setExceptionLogger(ExceptionLogger.NO_OP).setHandlerMapper(mapper).create();
-
-        server.start();
-    }
-
-    @AfterAll
-    static void shutdown() {
-        server.shutdown(5L, TimeUnit.SECONDS);
-    }
-
-    @BeforeEach
-    void setup() throws Exception {
-        mail = MailUtil.createMockMail2Recipients(MimeMessageUtil.mimeMessageFromStream(
-                ClassLoader.getSystemResourceAsStream("mime/sendToRemoteHttp.mime")));
-    }
-
-    @AfterEach
-    void cleanMapper() {
-        mapper.unregister(urlTestPattern);
-    }
-
-    @Test
-    void shouldBeFailedWhenServiceNotExists() throws Exception {
-        urlTestPattern = "/path/to/service/failed";
-
-        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
-                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
-                .setProperty("url", "http://qwerty.localhost:123456" + urlTestPattern).build();
-
-        Mailet mailet = new HeadersToHTTP();
-        mailet.init(mailetConfig);
-
-        mailet.service(mail);
-
-        assertThat(mail.getMessage().getHeader("X-headerToHTTP"))
-            .hasSize(1)
-            .allSatisfy((header) -> assertThat(header).isEqualTo("Failed"));
-        assertThat(mail.getMessage().getHeader("X-headerToHTTPFailure"))
-            .hasSize(1)
-            .allSatisfy((header) -> assertThat(header).isNotBlank());
-    }
-
-    @Test
-    void shouldBeSucceededWhenServiceResponseIsOk() throws Exception {
-        urlTestPattern = "/path/to/service/succeeded";
-
-        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
-                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
-                .setProperty("url", "http://" + server.getInetAddress().getHostAddress() + ":"
-                        + server.getLocalPort() + urlTestPattern)
-                .build();
-
-        mapper.register(urlTestPattern, (request, response, context) -> response.setStatusCode(HttpStatus.SC_OK));
-
-        Mailet mailet = new HeadersToHTTP();
-        mailet.init(mailetConfig);
-
-        mailet.service(mail);
-
-        assertThat(mail.getMessage().getHeader("X-headerToHTTP"))
-            .hasSize(1)
-            .allSatisfy((header) -> assertThat(header).isEqualTo("Succeeded"));
-    }
-
-    @Test
-    void serviceShouldNotModifyHeadersContent() throws Exception {
-        urlTestPattern = "/path/to/service/succeeded";
-
-        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
-                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
-                .setProperty("url", "http://" + server.getInetAddress().getHostAddress() + ":"
-                        + server.getLocalPort() + urlTestPattern)
-                .build();
-
-        mapper.register(urlTestPattern, (request, response, context) -> {
-
-            assertThat(request.getRequestLine().getMethod()).isEqualTo("POST");
-
-            BasicHttpEntityEnclosingRequest basicRequest = (BasicHttpEntityEnclosingRequest) request;
-            BasicHttpEntity entity = (BasicHttpEntity) basicRequest.getEntity();
-
-            try {
-                List<NameValuePair> params = URLEncodedUtils.parse(entity);
-                assertThat(params).hasSize(5).anySatisfy((param) -> {
-                    assertThat(param.getName()).isEqualTo("pKey");
-                    assertThat(param.getValue()).isEqualTo("pValue");
-                }).anySatisfy((param) -> {
-                    assertThat(param.getName()).isEqualTo("subject");
-                    assertThat(param.getValue()).isEqualTo("Fwd: Invitation: (Aucun objet) - "
-                            + "ven. 20 janv. 2017 14:00 - 15:00 (CET) (aduprat@linagora.com)");
-                }).anySatisfy((param) -> {
-                    assertThat(param.getName()).isEqualTo("message_id");
-                    assertThat(param.getValue())
-                            .isEqualTo("<f1...@linagora.com>");
-                }).anySatisfy((param) -> {
-                    assertThat(param.getName()).isEqualTo("reply_to");
-                    assertThat(param.getValue()).isEqualTo("[aduprat <du...@linagora.com>]");
-                }).anySatisfy((param) -> {
-                    assertThat(param.getName()).isEqualTo("size");
-                    assertThat(param.getValue()).isEqualTo("5242");
-                });
-
-            } finally {
-                EntityUtils.consume(basicRequest.getEntity());
-            }
-            response.setStatusCode(HttpStatus.SC_OK);
-        });
-
-        Mailet mailet = new HeadersToHTTP();
-        mailet.init(mailetConfig);
-
-        mailet.service(mail);
-
-    }
-
-    @Test
-    void shouldSetTheMailStateWhenPassThroughIsFalse() throws Exception {
-        urlTestPattern = "/path/to/service/PassThroughIsFalse";
-
-        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
-                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
-                .setProperty("url",
-                        "http://" + server.getInetAddress().getHostAddress() + ":"
-                                + server.getLocalPort() + urlTestPattern)
-                .setProperty("passThrough", "false").build();
-
-        mapper.register(urlTestPattern, (request, response, context) -> response.setStatusCode(HttpStatus.SC_OK));
-
-        Mailet mailet = new HeadersToHTTP();
-        mailet.init(mailetConfig);
-
-        mailet.service(mail);
-
-        assertThat(mail.getMessage().getHeader("X-headerToHTTP")).isNull();
-
-        assertThat(mail.getState()).isEqualTo(Mail.GHOST);
-    }
-
-    @Test
-    void shouldThrowMessagingExceptionWhenInvalidUrl() {
-        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
-                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
-                .setProperty("url", "qwerty://invalid.url").build();
-
-        assertThatThrownBy(() -> new HeadersToHTTP().init(mailetConfig))
-            .isExactlyInstanceOf(MessagingException.class)
-            .hasMessageContaining("Unable to contruct URL object from url");
-    }
-
-    @Test
-    void shouldThrowMessagingExceptionWhenUrlIsNull() {
-        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
-                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
-                .build();
-
-        assertThatThrownBy(() -> new HeadersToHTTP().init(mailetConfig))
-            .isExactlyInstanceOf(MessagingException.class)
-            .hasMessageContaining("Please configure a targetUrl (\"url\")");
-    }
-
-}
+/****************************************************************
+ * 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.transport.mailets;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import javax.mail.MessagingException;
+
+import org.apache.http.ExceptionLogger;
+import org.apache.http.HttpStatus;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.utils.URLEncodedUtils;
+import org.apache.http.config.SocketConfig;
+import org.apache.http.entity.BasicHttpEntity;
+import org.apache.http.impl.bootstrap.HttpServer;
+import org.apache.http.impl.bootstrap.ServerBootstrap;
+import org.apache.http.message.BasicHttpEntityEnclosingRequest;
+import org.apache.http.protocol.UriHttpRequestHandlerMapper;
+import org.apache.http.util.EntityUtils;
+import org.apache.james.util.MimeMessageUtil;
+import org.apache.mailet.Mail;
+import org.apache.mailet.Mailet;
+import org.apache.mailet.base.test.FakeMailetConfig;
+import org.apache.mailet.base.test.MailUtil;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+class HeadersToHTTPTest {
+
+    private static HttpServer server;
+    private static UriHttpRequestHandlerMapper mapper;
+    private Mail mail;
+
+    private String urlTestPattern;
+
+    @BeforeAll
+    static void setupServer() throws Exception {
+        mapper = new UriHttpRequestHandlerMapper();
+
+        SocketConfig socketConfig = SocketConfig.custom().setSoTimeout(50000).build();
+        server = ServerBootstrap.bootstrap().setListenerPort(0).setSocketConfig(socketConfig)
+                .setExceptionLogger(ExceptionLogger.NO_OP).setHandlerMapper(mapper).create();
+
+        server.start();
+    }
+
+    @AfterAll
+    static void shutdown() {
+        server.shutdown(5L, TimeUnit.SECONDS);
+    }
+
+    @BeforeEach
+    void setup() throws Exception {
+        mail = MailUtil.createMockMail2Recipients(MimeMessageUtil.mimeMessageFromStream(
+                ClassLoader.getSystemResourceAsStream("mime/sendToRemoteHttp.mime")));
+    }
+
+    @AfterEach
+    void cleanMapper() {
+        mapper.unregister(urlTestPattern);
+    }
+
+    @Test
+    void shouldBeFailedWhenServiceNotExists() throws Exception {
+        urlTestPattern = "/path/to/service/failed";
+
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
+                .setProperty("url", "http://qwerty.localhost:12345" + urlTestPattern).build();
+
+        Mailet mailet = new HeadersToHTTP();
+        mailet.init(mailetConfig);
+
+        mailet.service(mail);
+
+        assertThat(mail.getMessage().getHeader("X-headerToHTTP"))
+            .hasSize(1)
+            .allSatisfy((header) -> assertThat(header).isEqualTo("Failed"));
+        assertThat(mail.getMessage().getHeader("X-headerToHTTPFailure"))
+            .hasSize(1)
+            .allSatisfy((header) -> assertThat(header).isNotBlank());
+    }
+
+    @Test
+    void shouldBeSucceededWhenServiceResponseIsOk() throws Exception {
+        urlTestPattern = "/path/to/service/succeeded";
+
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
+                .setProperty("url", "http://" + server.getInetAddress().getHostAddress() + ":"
+                        + server.getLocalPort() + urlTestPattern)
+                .build();
+
+        mapper.register(urlTestPattern, (request, response, context) -> response.setStatusCode(HttpStatus.SC_OK));
+
+        Mailet mailet = new HeadersToHTTP();
+        mailet.init(mailetConfig);
+
+        mailet.service(mail);
+
+        assertThat(mail.getMessage().getHeader("X-headerToHTTP"))
+            .hasSize(1)
+            .allSatisfy((header) -> assertThat(header).isEqualTo("Succeeded"));
+    }
+
+    @Test
+    void serviceShouldNotModifyHeadersContent() throws Exception {
+        urlTestPattern = "/path/to/service/succeeded";
+
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
+                .setProperty("url", "http://" + server.getInetAddress().getHostAddress() + ":"
+                        + server.getLocalPort() + urlTestPattern)
+                .build();
+
+        mapper.register(urlTestPattern, (request, response, context) -> {
+
+            assertThat(request.getRequestLine().getMethod()).isEqualTo("POST");
+
+            BasicHttpEntityEnclosingRequest basicRequest = (BasicHttpEntityEnclosingRequest) request;
+            BasicHttpEntity entity = (BasicHttpEntity) basicRequest.getEntity();
+
+            try {
+                List<NameValuePair> params = URLEncodedUtils.parse(entity);
+                assertThat(params).hasSize(5).anySatisfy((param) -> {
+                    assertThat(param.getName()).isEqualTo("pKey");
+                    assertThat(param.getValue()).isEqualTo("pValue");
+                }).anySatisfy((param) -> {
+                    assertThat(param.getName()).isEqualTo("subject");
+                    assertThat(param.getValue()).isEqualTo("Fwd: Invitation: (Aucun objet) - "
+                            + "ven. 20 janv. 2017 14:00 - 15:00 (CET) (aduprat@linagora.com)");
+                }).anySatisfy((param) -> {
+                    assertThat(param.getName()).isEqualTo("message_id");
+                    assertThat(param.getValue())
+                            .isEqualTo("<f1...@linagora.com>");
+                }).anySatisfy((param) -> {
+                    assertThat(param.getName()).isEqualTo("reply_to");
+                    assertThat(param.getValue()).isEqualTo("[aduprat <du...@linagora.com>]");
+                }).anySatisfy((param) -> {
+                    assertThat(param.getName()).isEqualTo("size");
+                    assertThat(param.getValue()).isEqualTo("5242");
+                });
+
+            } finally {
+                EntityUtils.consume(basicRequest.getEntity());
+            }
+            response.setStatusCode(HttpStatus.SC_OK);
+        });
+
+        Mailet mailet = new HeadersToHTTP();
+        mailet.init(mailetConfig);
+
+        mailet.service(mail);
+
+    }
+
+    @Test
+    void shouldSetTheMailStateWhenPassThroughIsFalse() throws Exception {
+        urlTestPattern = "/path/to/service/PassThroughIsFalse";
+
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
+                .setProperty("url",
+                        "http://" + server.getInetAddress().getHostAddress() + ":"
+                                + server.getLocalPort() + urlTestPattern)
+                .setProperty("passThrough", "false").build();
+
+        mapper.register(urlTestPattern, (request, response, context) -> response.setStatusCode(HttpStatus.SC_OK));
+
+        Mailet mailet = new HeadersToHTTP();
+        mailet.init(mailetConfig);
+
+        mailet.service(mail);
+
+        assertThat(mail.getMessage().getHeader("X-headerToHTTP")).isNull();
+
+        assertThat(mail.getState()).isEqualTo(Mail.GHOST);
+    }
+
+    @Test
+    void shouldThrowMessagingExceptionWhenInvalidUrl() {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
+                .setProperty("url", "qwerty://invalid.url").build();
+
+        assertThatThrownBy(() -> new HeadersToHTTP().init(mailetConfig))
+            .isExactlyInstanceOf(MessagingException.class)
+            .hasMessageContaining("Unable to contruct URL object from url");
+    }
+
+    @Test
+    void shouldThrowMessagingExceptionWhenUrlIsNull() {
+        FakeMailetConfig mailetConfig = FakeMailetConfig.builder()
+                .setProperty("parameterKey", "pKey").setProperty("parameterValue", "pValue")
+                .build();
+
+        assertThatThrownBy(() -> new HeadersToHTTP().init(mailetConfig))
+            .isExactlyInstanceOf(MessagingException.class)
+            .hasMessageContaining("Please configure a targetUrl (\"url\")");
+    }
+
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 03/10: JAMES-2904 Improve Mailbox Reindexing efficiency

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 3d8fdf5fcef9b999a3b6d45ba20022bfe1a34294
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Nov 21 16:59:52 2019 +0700

    JAMES-2904 Improve Mailbox Reindexing efficiency
---
 .../main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java b/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
index 390c557..0f8cb27 100644
--- a/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
+++ b/mailbox/tools/indexer/src/main/java/org/apache/mailbox/tools/indexer/ReIndexerPerformer.java
@@ -78,8 +78,7 @@ public class ReIndexerPerformer {
         try {
             return Iterators.toStream(
                 mailboxSessionMapperFactory.getMessageMapper(mailboxSession)
-                    .findInMailbox(mailbox, MessageRange.all(), MessageMapper.FetchType.Metadata, NO_LIMIT))
-                .map(MailboxMessage::getUid)
+                    .listAllMessageUids(mailbox))
                 .map(uid -> handleMessageReIndexing(mailboxSession, mailbox, uid, reprocessingContext))
                 .reduce(Task::combine)
                 .orElse(Task.Result.COMPLETED);


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 04/10: JAMES-2904 MessageResult::hasAttachment

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit f1ca51e39dca8d92e171023a20fb1b2171dada89
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Nov 21 17:20:11 2019 +0700

    JAMES-2904 MessageResult::hasAttachment
    
    This method is callable at Metadata level on top of Cassandra but needs some
    message content parsing for JPA or MailDir
---
 .../apache/james/mailbox/model/MessageResult.java  | 12 +++-
 .../apache/james/mailbox/MailboxManagerTest.java   | 45 +++++++++++++++
 .../src/test/resources/eml/twoAttachmentsApi.eml   | 64 ++++++++++++++++++++++
 .../cassandra/mail/CassandraMessageDAO.java        | 21 ++++---
 .../cassandra/mail/MessageWithoutAttachment.java   |  7 ++-
 .../cassandra/table/CassandraMessageV2Table.java   |  4 +-
 .../model/openjpa/AbstractJPAMailboxMessage.java   |  5 ++
 .../mailbox/maildir/mail/model/MaildirMessage.java |  5 ++
 .../james/mailbox/store/MessageResultImpl.java     |  7 ++-
 .../mailbox/store/StoreMessageResultIterator.java  |  7 ++-
 .../store/mail/model/DelegatingMailboxMessage.java |  5 ++
 .../james/mailbox/store/mail/model/Message.java    |  2 +
 .../mail/model/impl/SimpleMailboxMessage.java      | 31 +++++++++--
 .../store/mail/model/impl/SimpleMessage.java       |  9 ++-
 .../store/AbstractMessageIdManagerStorageTest.java | 31 +++++++++++
 .../mailbox/store/MessageIdManagerTestSystem.java  |  3 +
 16 files changed, 236 insertions(+), 22 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageResult.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageResult.java
index 35a9329..7393e7d 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageResult.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageResult.java
@@ -253,8 +253,18 @@ public interface MessageResult extends Comparable<MessageResult> {
 
     
     Headers getHeaders() throws MailboxException;
-    
+
+    /**
+     * Returns the list of loaded attachments depending on the fetchType.
+     *
+     * These attachments will be loaded only for Full
+     */
     List<MessageAttachment> getAttachments() throws MailboxException;
+
+    /**
+     * Indicates if the message have attachments, regardless of loaded attachments.
+     */
+    boolean hasAttachments() throws MailboxException;
     
     /**
      * Describes a path within a multipart MIME message. All implementations
diff --git a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java
index 6293e57..fac59ae 100644
--- a/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java
+++ b/mailbox/api/src/test/java/org/apache/james/mailbox/MailboxManagerTest.java
@@ -70,6 +70,7 @@ import org.apache.james.mailbox.model.MailboxPath;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageResult;
+import org.apache.james.mailbox.model.MessageResultIterator;
 import org.apache.james.mailbox.model.MultimailboxesSearchQuery;
 import org.apache.james.mailbox.model.Quota;
 import org.apache.james.mailbox.model.QuotaRoot;
@@ -77,6 +78,7 @@ import org.apache.james.mailbox.model.SearchQuery;
 import org.apache.james.mailbox.model.search.MailboxQuery;
 import org.apache.james.mailbox.util.EventCollector;
 import org.apache.james.mime4j.dom.Message;
+import org.apache.james.util.ClassLoaderUtils;
 import org.apache.james.util.concurrency.ConcurrentTestRunner;
 import org.assertj.core.api.SoftAssertions;
 import org.junit.jupiter.api.AfterEach;
@@ -85,9 +87,11 @@ import org.junit.jupiter.api.Nested;
 import org.junit.jupiter.api.Test;
 import org.mockito.ArgumentCaptor;
 
+import com.github.fge.lambdas.Throwing;
 import com.google.common.base.Strings;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSet;
+
 import reactor.core.publisher.Mono;
 
 /**
@@ -1804,4 +1808,45 @@ public abstract class MailboxManagerTest<T extends MailboxManager> {
             }
         }
     }
+
+    @Nested
+    class MessageTests {
+        private MessageManager inboxManager;
+
+        @BeforeEach
+        void setUp() throws Exception {
+            session = mailboxManager.createSystemSession(USER_1);
+            MailboxPath inbox = MailboxPath.inbox(session);
+            mailboxManager.createMailbox(inbox, session).get();
+            inboxManager = mailboxManager.getMailbox(inbox, session);
+        }
+
+        @Test
+        void getMessagesShouldIncludeHasAttachmentInformation() throws Exception {
+            ComposedMessageId composeId = inboxManager.appendMessage(AppendCommand.builder()
+                .withFlags(new Flags(Flags.Flag.DELETED))
+                .build(ClassLoaderUtils.getSystemResourceAsSharedStream("eml/twoAttachmentsApi.eml")), session);
+
+            MessageResultIterator messages = inboxManager.getMessages(MessageRange.one(composeId.getUid()), FetchGroupImpl.MINIMAL, session);
+
+            assertThat(messages).toIterable()
+                .hasSize(1)
+                .first()
+                .satisfies(Throwing.consumer(messageResult -> assertThat(messageResult.hasAttachments()).isTrue()));
+        }
+
+        @Test
+        void getMessagesShouldNotIncludeAttachmentInformationWhenNone() throws Exception {
+            ComposedMessageId composeId = inboxManager.appendMessage(AppendCommand.builder()
+                .withFlags(new Flags(Flags.Flag.DELETED))
+                .build(message), session);
+
+            MessageResultIterator messages = inboxManager.getMessages(MessageRange.one(composeId.getUid()), FetchGroupImpl.MINIMAL, session);
+
+            assertThat(messages).toIterable()
+                .hasSize(1)
+                .first()
+                .satisfies(Throwing.consumer(messageResult -> assertThat(messageResult.hasAttachments()).isFalse()));
+        }
+    }
 }
diff --git a/mailbox/api/src/test/resources/eml/twoAttachmentsApi.eml b/mailbox/api/src/test/resources/eml/twoAttachmentsApi.eml
new file mode 100644
index 0000000..c93a59d
--- /dev/null
+++ b/mailbox/api/src/test/resources/eml/twoAttachmentsApi.eml
@@ -0,0 +1,64 @@
+Return-Path: <fr...@linagora.com>
+X-Priority: 3 (Normal)
+From: "From"
+ <fr...@linagora.com>
+To: "To"
+ <to...@linagora.com>
+Subject: [8/10]Attached Image light with text
+Date: Fri, 27 Mar 2015 21:48:38 +0100
+Message-Id: <20...@canondir.par.lng>
+Mime-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="AHNPACBLDCDIDAGGGDDFAABECGCA"
+
+--AHNPACBLDCDIDAGGGDDFAABECGCA
+Content-Type: text/html; charset=utf-8; format=flowed
+Content-Transfer-Encoding: 8bit
+
+<b>html</b>
+
+--AHNPACBLDCDIDAGGGDDFAABECGCA
+Content-Type: image/jpeg;
+ name="4037_014.jpg"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment;
+ filename="4037_014.jpg"
+
+/9j/4X2cRXhpZgAASUkqAAgAAAANAA8BAgAKAAAAqgAAABABAgAJAAAAtAAAABIBAwABAAAA
+AQAAABoBBQABAAAAvgAAABsBBQABAAAAxgAAACgBAwABAAAAAgAAADEBAgAKAAAAzgAAADIB
+AgAUAAAA2AAAABMCAwABAAAAAgAAAGmHBAABAAAAfAIAAKXEBwDQAAAA7AAAANLGBwBAAAAA
+vAEAANPGBwCAAAAA/AEAAEwqAABQYW5hc29uaWMARE1DLUZaNDUAALQAAAABAAAAtAAAAAEA
+AABWZXIuMS4wICAAMjAxNDowMjoyNSAxMDozMjowOQBQcmludElNADAyNTAAAA4AAQAWABYA
+AgAAAAAAAwBkAAAABwAAAAAACAAAAAAACQAAAAAACgAAAAAACwCsAAAADAAAAAAADQAAAAAA
+DgDEAAAAAAEFAAAAAQEBAAAAEAGAAAAACREAABAnAAALDwAAECcAAJcFAAAQJwAAsAgAABAn
+AAABHAAAECcAAF4CAAAQJwAAiwAAABAnAADLAwAAECcAAOUbAAAQJwAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+
+--AHNPACBLDCDIDAGGGDDFAABECGCA
+Content-Type: image/jpeg;
+ name="4037_015.jpg"
+Content-Transfer-Encoding: base64
+Content-Disposition: attachment;
+ filename="4037_015.jpg"
+
+iVBORw0KGgoAAAANSUhEUgAABYUAAAL4CAIAAACrzA8fAAAACXBIWXMAAAsTAAALEwEAmpwY
+AAAAB3RJTUUH3wMNDiUMca0XkQAAIABJREFUeNq8vWm0bdlVHja/tc+99zX13qv2VSeVmlIv
+FSqEOhA2AoEhxMRBg8QOyEkG6WMDSZzhMQTGDDcwiJPhBBMby4SMDJthgmOMAYvGMcF0QgIU
+WRKobymp+qpX9fp779nry4+9mjnnWuuc80qMvCpdvXrv3nP22Xutueb85je/D1/3+q+ipF9z
+nGfGdZznGCMjKaSIkJQwBYSAEMI0Tatptdrb21utVqvVtJKAAAABEAAiUP+IiECYfsfyJf1B
+10+cOHH48OGVlZVSypaWlv379zc2Nr722msNDQ2u+y9zaYQeAQAAAACCHgEAAAB0y969e+ON
+KnpOe3v7JZdccj6fwPXr10+aNKnAB956663Zs2fjTgMAAADOKzhOAQAAAFCYs+yO0XfNNQAA
+AAAA/nNBfgQAAADQDVddddW6detSqdQZ7JvL5W655RZIEgAAAAAAEayKigqcBQAAAKAAhw8f
+3rZt25AhQwYNGpTJZHq4V2tr6/bt25csWbJjxw6cQwAAAACACMiPAAAAAAAAAAAAQH8D/wgA
+AAAAAAAAAAD0N9AjAAAAAAAAAAAA0N9AjwAAAAAAAAAAAEB/Az0CAAAAAAAAAAAA/Q30CAAA
+AAAAAAAAAPQ30CMAAAAAAAAAAADQ30CPAAAAAAAAAAAAQH/z/0IKJwmNQbpqAAAAAElFTkSu
+QmCC
+
+--AHNPACBLDCDIDAGGGDDFAABECGCA--
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
index 37976ab..b29e7e8 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/CassandraMessageDAO.java
@@ -270,8 +270,9 @@ public class CassandraMessageDAO {
                     getPropertyBuilder(row),
                     messageId.getMailboxId(),
                     messageId.getUid(),
-                    messageIdWithMetaData.getModSeq());
-            return found(Pair.of(messageWithoutAttachment, getAttachments(row, fetchType)));
+                    messageIdWithMetaData.getModSeq(),
+                    hasAttachment(row));
+            return found(Pair.of(messageWithoutAttachment, getAttachments(row)));
         });
     }
 
@@ -288,16 +289,14 @@ public class CassandraMessageDAO {
         return new Property(udtValue.getString(Properties.NAMESPACE), udtValue.getString(Properties.NAME), udtValue.getString(Properties.VALUE));
     }
 
-    private Stream<MessageAttachmentRepresentation> getAttachments(Row row, FetchType fetchType) {
-        switch (fetchType) {
-            case Full:
-            case Body:
-                List<UDTValue> udtValues = row.getList(ATTACHMENTS, UDTValue.class);
+    private Stream<MessageAttachmentRepresentation> getAttachments(Row row) {
+        List<UDTValue> udtValues = row.getList(ATTACHMENTS, UDTValue.class);
+        return attachmentByIds(udtValues);
+    }
 
-                return attachmentByIds(udtValues);
-            default:
-                return Stream.of();
-        }
+    private boolean hasAttachment(Row row) {
+        List<UDTValue> udtValues = row.getList(ATTACHMENTS, UDTValue.class);
+        return !udtValues.isEmpty();
     }
 
     private Stream<MessageAttachmentRepresentation> attachmentByIds(List<UDTValue> udtValues) {
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageWithoutAttachment.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageWithoutAttachment.java
index 89f57b2..226e8bc 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageWithoutAttachment.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/mail/MessageWithoutAttachment.java
@@ -21,6 +21,7 @@ package org.apache.james.mailbox.cassandra.mail;
 
 import java.util.Date;
 import java.util.List;
+
 import javax.mail.Flags;
 import javax.mail.util.SharedByteArrayInputStream;
 
@@ -44,9 +45,11 @@ public class MessageWithoutAttachment {
     private final MailboxId mailboxId;
     private final MessageUid messageUid;
     private final long modSeq;
+    private final boolean hasAttachment;
 
     public MessageWithoutAttachment(MessageId messageId, Date internalDate, Long size, Integer bodySize, SharedByteArrayInputStream content,
-                                    Flags flags, PropertyBuilder propertyBuilder, MailboxId mailboxId, MessageUid messageUid, long modSeq) {
+                                    Flags flags, PropertyBuilder propertyBuilder, MailboxId mailboxId, MessageUid messageUid, long modSeq,
+                                    boolean hasAttachment) {
         this.messageId = messageId;
         this.internalDate = internalDate;
         this.size = size;
@@ -57,6 +60,7 @@ public class MessageWithoutAttachment {
         this.mailboxId = mailboxId;
         this.messageUid = messageUid;
         this.modSeq = modSeq;
+        this.hasAttachment = hasAttachment;
     }
 
     public SimpleMailboxMessage toMailboxMessage(List<MessageAttachment> attachments) {
@@ -72,6 +76,7 @@ public class MessageWithoutAttachment {
             .flags(flags)
             .propertyBuilder(propertyBuilder)
             .addAttachments(attachments)
+            .hasAttachment(hasAttachment)
             .build();
     }
 
diff --git a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageV2Table.java b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageV2Table.java
index c2421f3..2d41173 100644
--- a/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageV2Table.java
+++ b/mailbox/cassandra/src/main/java/org/apache/james/mailbox/cassandra/table/CassandraMessageV2Table.java
@@ -35,8 +35,8 @@ public interface CassandraMessageV2Table {
     String ATTACHMENTS = "attachments";
 
     String[] FIELDS = { MESSAGE_ID, INTERNAL_DATE, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, BODY_CONTENT, HEADER_CONTENT, TEXTUAL_LINE_COUNT, PROPERTIES, ATTACHMENTS };
-    String[] METADATA = { MESSAGE_ID, INTERNAL_DATE, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, TEXTUAL_LINE_COUNT, PROPERTIES };
-    String[] HEADERS = { MESSAGE_ID, INTERNAL_DATE, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, HEADER_CONTENT, TEXTUAL_LINE_COUNT, PROPERTIES };
+    String[] METADATA = { MESSAGE_ID, INTERNAL_DATE, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, TEXTUAL_LINE_COUNT, PROPERTIES, ATTACHMENTS };
+    String[] HEADERS = { MESSAGE_ID, INTERNAL_DATE, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, HEADER_CONTENT, TEXTUAL_LINE_COUNT, PROPERTIES, ATTACHMENTS };
     String[] BODY = { MESSAGE_ID, INTERNAL_DATE, BODY_START_OCTET, FULL_CONTENT_OCTETS, BODY_OCTECTS, BODY_CONTENT, TEXTUAL_LINE_COUNT, PROPERTIES, ATTACHMENTS };
 
     interface Properties {
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
index 6277c72..55986fc 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMailboxMessage.java
@@ -510,4 +510,9 @@ public abstract class AbstractJPAMailboxMessage implements MailboxMessage {
         }
     }
 
+    @Override
+    public boolean hasAttachment() {
+        return !getAttachments().isEmpty();
+    }
+
 }
diff --git a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
index a9e37b6..5826657 100644
--- a/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
+++ b/mailbox/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
@@ -275,4 +275,9 @@ public class MaildirMessage implements Message {
         }
     }
 
+    @Override
+    public boolean hasAttachment() {
+        return !getAttachments().isEmpty();
+    }
+
 }
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageResultImpl.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageResultImpl.java
index 18cb8ea..308873c 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageResultImpl.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageResultImpl.java
@@ -312,7 +312,12 @@ public class MessageResultImpl implements MessageResult {
     public List<MessageAttachment> getAttachments() {
         return message.getAttachments();
     }
-    
+
+    @Override
+    public boolean hasAttachments() {
+        return message.hasAttachment();
+    }
+
     private static final class HeadersImpl implements Headers {
 
         private final MailboxMessage msg;
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageResultIterator.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageResultIterator.java
index 8bc1f43..707e671 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageResultIterator.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageResultIterator.java
@@ -265,7 +265,12 @@ public class StoreMessageResultIterator implements MessageResultIterator {
         public Content getBody() throws MailboxException {
             throw exception;
         }
-        
+
+        @Override
+        public boolean hasAttachments() throws MailboxException {
+            throw exception;
+        }
+
         @Override
         public int compareTo(MessageResult that) {
             return getUid().compareTo(that.getUid());
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java
index 46e5a94..4f09b14 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/DelegatingMailboxMessage.java
@@ -119,4 +119,9 @@ public abstract class DelegatingMailboxMessage implements MailboxMessage {
     public List<MessageAttachment> getAttachments() {
         return message.getAttachments();
     }
+
+    @Override
+    public boolean hasAttachment() {
+        return message.hasAttachment();
+    }
 }
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
index 3f46ad4..e732d21 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
@@ -109,4 +109,6 @@ public interface Message {
      */
     List<MessageAttachment> getAttachments();
 
+    boolean hasAttachment();
+
 }
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java
index 4adfb49..c947f25 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMailboxMessage.java
@@ -64,6 +64,7 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
         private Optional<MessageUid> uid = Optional.empty();
         private Optional<Long> modseq = Optional.empty();
         private ImmutableList.Builder<MessageAttachment> attachments = ImmutableList.builder();
+        private Optional<Boolean> hasAttachment = Optional.empty();
 
         public Builder messageId(MessageId messageId) {
             this.messageId = messageId;
@@ -103,6 +104,16 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
             return this;
         }
 
+        public Builder hasAttachment() {
+            this.hasAttachment = Optional.of(true);
+            return this;
+        }
+
+        public Builder hasAttachment(boolean hasAttachment) {
+            this.hasAttachment = Optional.of(hasAttachment);
+            return this;
+        }
+
         public Builder flags(Flags flags) {
             this.flags = flags;
             return this;
@@ -133,8 +144,10 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
             Preconditions.checkNotNull(propertyBuilder, "propertyBuilder is required");
             Preconditions.checkNotNull(mailboxId, "mailboxId is required");
 
+            ImmutableList<MessageAttachment> attachments = this.attachments.build();
+            boolean hasAttachment = this.hasAttachment.orElse(!attachments.isEmpty());
             SimpleMailboxMessage simpleMailboxMessage = new SimpleMailboxMessage(messageId, internalDate, size,
-                bodyStartOctet, content, flags, propertyBuilder, mailboxId, attachments.build());
+                bodyStartOctet, content, flags, propertyBuilder, mailboxId, attachments, hasAttachment);
 
             uid.ifPresent(simpleMailboxMessage::setUid);
             modseq.ifPresent(simpleMailboxMessage::setModSeq);
@@ -162,6 +175,7 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
             .internalDate(original.getInternalDate())
             .size(original.getFullContentOctets())
             .flags(original.createFlags())
+            .hasAttachment(original.hasAttachment())
             .propertyBuilder(propertyBuilder);
     }
 
@@ -191,7 +205,8 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
 
     public SimpleMailboxMessage(MessageId messageId, Date internalDate, long size, int bodyStartOctet,
             SharedInputStream content, Flags flags,
-            PropertyBuilder propertyBuilder, MailboxId mailboxId, List<MessageAttachment> attachments) {
+            PropertyBuilder propertyBuilder, MailboxId mailboxId, List<MessageAttachment> attachments,
+            boolean hasAttachment) {
         super(new SimpleMessage(
                 messageId,
                 content, size, internalDate, propertyBuilder.getSubType(),
@@ -199,8 +214,8 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
                 bodyStartOctet,
                 propertyBuilder.getTextualLineCount(),
                 propertyBuilder.toProperties(),
-                attachments
-                ));
+                attachments,
+                hasAttachment));
 
             setFlags(flags);
             this.mailboxId = mailboxId;
@@ -208,6 +223,14 @@ public class SimpleMailboxMessage extends DelegatingMailboxMessage {
     }
 
     public SimpleMailboxMessage(MessageId messageId, Date internalDate, long size, int bodyStartOctet,
+            SharedInputStream content, Flags flags,
+            PropertyBuilder propertyBuilder, MailboxId mailboxId, List<MessageAttachment> attachments) {
+        this(messageId, internalDate, size, bodyStartOctet,
+            content, flags,
+            propertyBuilder, mailboxId, attachments, !attachments.isEmpty());
+    }
+
+    public SimpleMailboxMessage(MessageId messageId, Date internalDate, long size, int bodyStartOctet,
                                 SharedInputStream content, Flags flags,
                                 PropertyBuilder propertyBuilder, MailboxId mailboxId) {
         this(messageId, internalDate, size, bodyStartOctet,
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java
index 69d3d85..0302fe5 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/model/impl/SimpleMessage.java
@@ -42,8 +42,9 @@ public class SimpleMessage implements Message {
     private final Long textualLineCount;
     private final List<Property> properties;
     private final List<MessageAttachment> attachments;
+    private final boolean hasAttachments;
 
-    public SimpleMessage(MessageId messageId, SharedInputStream content, long size, Date internalDate, String subType, String mediaType, int bodyStartOctet, Long textualLineCount, List<Property> properties, List<MessageAttachment> attachments) {
+    public SimpleMessage(MessageId messageId, SharedInputStream content, long size, Date internalDate, String subType, String mediaType, int bodyStartOctet, Long textualLineCount, List<Property> properties, List<MessageAttachment> attachments, boolean hasAttachments) {
         this.messageId = messageId;
         this.subType = subType;
         this.mediaType = mediaType;
@@ -54,6 +55,7 @@ public class SimpleMessage implements Message {
         this.textualLineCount = textualLineCount;
         this.properties = properties;
         this.attachments = attachments;
+        this.hasAttachments = hasAttachments;
     }
 
     @Override
@@ -124,4 +126,9 @@ public class SimpleMessage implements Message {
     public List<MessageAttachment> getAttachments() {
         return attachments;
     }
+
+    @Override
+    public boolean hasAttachment() {
+        return hasAttachments;
+    }
 }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java
index 966ff22..9099406 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/AbstractMessageIdManagerStorageTest.java
@@ -47,9 +47,11 @@ import org.apache.james.mailbox.model.MailboxACL.Right;
 import org.apache.james.mailbox.model.MailboxId;
 import org.apache.james.mailbox.model.MessageId;
 import org.apache.james.mailbox.model.MessageResult;
+import org.apache.james.util.ClassLoaderUtils;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
+import com.github.fge.lambdas.Throwing;
 import com.github.steveash.guavate.Guavate;
 import com.google.common.collect.ImmutableList;
 
@@ -980,4 +982,33 @@ public abstract class AbstractMessageIdManagerStorageTest {
             .extracting(MessageResult::getFlags)
             .containsOnly(flags);
     }
+
+    @Test
+    void getMessagesShouldIncludeAttachmentInformation() throws Exception {
+        MessageId messageId = testingData.getMailboxManager().getMailbox(bobMailbox1.getMailboxId(), bobSession)
+            .appendMessage(MessageManager.AppendCommand.builder()
+            .withFlags(new Flags(Flags.Flag.DELETED))
+            .build(ClassLoaderUtils.getSystemResourceAsSharedStream("eml/twoAttachmentsApi.eml")), bobSession)
+            .getMessageId();
+
+        List<MessageResult> messages = messageIdManager.getMessages(ImmutableList.of(messageId), FetchGroupImpl.MINIMAL, bobSession);
+
+        assertThat(messages)
+            .hasSize(1)
+            .first()
+            .satisfies(Throwing.consumer(messageResult -> assertThat(messageResult.hasAttachments()).isTrue()));
+    }
+
+    @Test
+    void getMessagesShouldNotIncludeAttachmentInformationWhenNone() throws Exception {
+        Flags flags = new Flags(Flags.Flag.FLAGGED);
+        MessageId messageId = testingData.persist(bobMailbox1.getMailboxId(), messageUid1, flags, bobSession);
+
+        List<MessageResult> messages = messageIdManager.getMessages(ImmutableList.of(messageId), FetchGroupImpl.MINIMAL, bobSession);
+
+        assertThat(messages)
+            .hasSize(1)
+            .first()
+            .satisfies(Throwing.consumer(messageResult -> assertThat(messageResult.hasAttachments()).isFalse()));
+    }
 }
diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java
index a0f56d2..30a4817 100644
--- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java
+++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/MessageIdManagerTestSystem.java
@@ -67,6 +67,9 @@ public class MessageIdManagerTestSystem {
         this.mailboxManager = mailboxManager;
     }
 
+    public StoreMailboxManager getMailboxManager() {
+        return mailboxManager;
+    }
 
     public MessageIdManager getMessageIdManager() {
         return messageIdManager;


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 05/10: JAMES-2904 MessageResult s/getAttachments/getLoadedAttachments

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 1259c208eef42c121b7588688988b48d2190ae8d
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Nov 21 18:40:03 2019 +0700

    JAMES-2904 MessageResult s/getAttachments/getLoadedAttachments
    
    This underlines the fact that attachments returned by this method depends
    on the fetchType
---
 .../api/src/main/java/org/apache/james/mailbox/model/MessageResult.java | 2 +-
 .../src/main/java/org/apache/james/mailbox/store/MessageResultImpl.java | 2 +-
 .../java/org/apache/james/mailbox/store/StoreMessageResultIterator.java | 2 +-
 .../src/main/java/org/apache/james/jmap/draft/MessageIdProbe.java       | 2 +-
 .../src/main/java/org/apache/james/jmap/draft/model/MessageFactory.java | 2 +-
 5 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageResult.java b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageResult.java
index 7393e7d..40f75cf 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageResult.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/MessageResult.java
@@ -259,7 +259,7 @@ public interface MessageResult extends Comparable<MessageResult> {
      *
      * These attachments will be loaded only for Full
      */
-    List<MessageAttachment> getAttachments() throws MailboxException;
+    List<MessageAttachment> getLoadedAttachments() throws MailboxException;
 
     /**
      * Indicates if the message have attachments, regardless of loaded attachments.
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageResultImpl.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageResultImpl.java
index 308873c..a39e379 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageResultImpl.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/MessageResultImpl.java
@@ -309,7 +309,7 @@ public class MessageResultImpl implements MessageResult {
     }
     
     @Override
-    public List<MessageAttachment> getAttachments() {
+    public List<MessageAttachment> getLoadedAttachments() {
         return message.getAttachments();
     }
 
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageResultIterator.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageResultIterator.java
index 707e671..68ddee2 100644
--- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageResultIterator.java
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/StoreMessageResultIterator.java
@@ -333,7 +333,7 @@ public class StoreMessageResultIterator implements MessageResultIterator {
         }
 
         @Override
-        public List<MessageAttachment> getAttachments() throws MailboxException {
+        public List<MessageAttachment> getLoadedAttachments() throws MailboxException {
             throw exception;
         }
 
diff --git a/server/container/guice/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/MessageIdProbe.java b/server/container/guice/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/MessageIdProbe.java
index 6240733..e6703fe 100644
--- a/server/container/guice/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/MessageIdProbe.java
+++ b/server/container/guice/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/MessageIdProbe.java
@@ -72,7 +72,7 @@ public class MessageIdProbe implements GuiceProbe {
             mailboxSession);
 
         return messages.stream()
-            .flatMap(Throwing.function(messageResult -> messageResult.getAttachments().stream()))
+            .flatMap(Throwing.function(messageResult -> messageResult.getLoadedAttachments().stream()))
             .map(MessageAttachment::getAttachmentId)
             .collect(Guavate.toImmutableList());
     }
diff --git a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageFactory.java b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageFactory.java
index 5a7eeef..a0e0359 100644
--- a/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageFactory.java
+++ b/server/protocols/jmap-draft/src/main/java/org/apache/james/jmap/draft/model/MessageFactory.java
@@ -233,7 +233,7 @@ public class MessageFactory {
                 .modSeq(messageResult.getModSeq())
                 .size(messageResult.getSize())
                 .internalDate(messageResult.getInternalDate().toInstant())
-                .attachments(messageResult.getAttachments())
+                .attachments(messageResult.getLoadedAttachments())
                 .mailboxId(messageResult.getMailboxId());
             try {
                 return builder.content(messageResult.getFullContent().getInputStream());


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 02/10: Fix logging for already created ElasticSearch index

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 7840311c0361983a4ffdd180a09e1246b39e8c5f
Author: Raphael Ouazana <ra...@linagora.com>
AuthorDate: Thu Nov 21 16:46:58 2019 +0100

    Fix logging for already created ElasticSearch index
---
 .../java/org/apache/james/backends/es/IndexCreationFactory.java  | 2 +-
 .../src/main/java/org/apache/james/backends/es/IndexName.java    | 9 +++++++++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexCreationFactory.java b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexCreationFactory.java
index 2910c91..9d6f834 100644
--- a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexCreationFactory.java
+++ b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexCreationFactory.java
@@ -120,7 +120,7 @@ public class IndexCreationFactory {
                             .source(settings), RequestOptions.DEFAULT);
             } catch (ElasticsearchStatusException exception) {
                 if (exception.getMessage().contains(INDEX_ALREADY_EXISTS_EXCEPTION_MESSAGE)) {
-                    LOGGER.info("Index [{}] already exist", indexName);
+                    LOGGER.info("Index [{}] already exists", indexName.getValue());
                 } else {
                     throw exception;
                 }
diff --git a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexName.java b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexName.java
index 4541f48..bfdddba 100644
--- a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexName.java
+++ b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexName.java
@@ -21,6 +21,8 @@ package org.apache.james.backends.es;
 
 import java.util.Objects;
 
+import com.google.common.base.MoreObjects;
+
 public class IndexName {
     private final String value;
 
@@ -46,4 +48,11 @@ public class IndexName {
     public final int hashCode() {
         return Objects.hash(value);
     }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("value", value)
+            .toString();
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 06/10: JAMES-2949 Username strong typing in IMAP Authentication

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 812ea668e03f09c3d0344a7b84aaa9c909f28f33
Author: Raphael Ouazana <ra...@linagora.com>
AuthorDate: Thu Nov 21 11:28:46 2019 +0100

    JAMES-2949 Username strong typing in IMAP Authentication
---
 .../james/imap/decode/parser/LoginCommandParser.java |  5 +++--
 .../james/imap/message/request/LoginRequest.java     |  7 ++++---
 .../james/imap/processor/AbstractAuthProcessor.java  | 20 ++++++++++----------
 .../james/imap/processor/AuthenticateProcessor.java  |  5 +++--
 4 files changed, 20 insertions(+), 17 deletions(-)

diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java
index 4c4246f..4f0a53f 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/LoginCommandParser.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.imap.decode.parser;
 
+import org.apache.james.core.Username;
 import org.apache.james.imap.api.ImapCommand;
 import org.apache.james.imap.api.ImapConstants;
 import org.apache.james.imap.api.ImapMessage;
@@ -39,8 +40,8 @@ public class LoginCommandParser extends AbstractImapCommandParser {
 
     @Override
     protected ImapMessage decode(ImapCommand command, ImapRequestLineReader request, Tag tag, ImapSession session) throws DecodingException {
-        final String userid = request.astring();
-        final String password = request.astring();
+        Username userid = Username.of(request.astring());
+        String password = request.astring();
         request.eol();
 
         return new LoginRequest(command, userid, password, tag);
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/request/LoginRequest.java b/protocols/imap/src/main/java/org/apache/james/imap/message/request/LoginRequest.java
index df18fef..17fee58 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/message/request/LoginRequest.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/message/request/LoginRequest.java
@@ -18,6 +18,7 @@
  ****************************************************************/
 package org.apache.james.imap.message.request;
 
+import org.apache.james.core.Username;
 import org.apache.james.imap.api.ImapCommand;
 import org.apache.james.imap.api.Tag;
 import org.apache.james.imap.api.message.request.ImapRequest;
@@ -26,11 +27,11 @@ import org.apache.james.imap.api.message.request.ImapRequest;
  * {@link ImapRequest} which requests the login of a user
  */
 public class LoginRequest extends AbstractImapRequest {
-    private final String userid;
+    private final Username userid;
 
     private final String password;
 
-    public LoginRequest(ImapCommand command, String userid, String password, Tag tag) {
+    public LoginRequest(ImapCommand command, Username userid, String password, Tag tag) {
         super(tag, command);
         this.userid = userid;
         this.password = password;
@@ -50,7 +51,7 @@ public class LoginRequest extends AbstractImapRequest {
      * 
      * @return user
      */
-    public final String getUserid() {
+    public final Username getUserid() {
         return userid;
     }
 }
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractAuthProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractAuthProcessor.java
index 77416a8..d7ef19e 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractAuthProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractAuthProcessor.java
@@ -68,7 +68,7 @@ public abstract class AbstractAuthProcessor<R extends ImapRequest> extends Abstr
             if (!authFailure) {
                 final MailboxManager mailboxManager = getMailboxManager();
                 try {
-                    final MailboxSession mailboxSession = mailboxManager.login(Username.of(authenticationAttempt.getAuthenticationId()),
+                    final MailboxSession mailboxSession = mailboxManager.login(authenticationAttempt.getAuthenticationId(),
                         authenticationAttempt.getPassword());
                     session.authenticated();
                     session.setAttribute(ImapSessionUtils.MAILBOX_SESSION_ATTRIBUTE_SESSION_KEY, mailboxSession);
@@ -97,9 +97,9 @@ public abstract class AbstractAuthProcessor<R extends ImapRequest> extends Abstr
             if (!authFailure) {
                 final MailboxManager mailboxManager = getMailboxManager();
                 try {
-                    final MailboxSession mailboxSession = mailboxManager.loginAsOtherUser(Username.of(authenticationAttempt.getAuthenticationId()),
+                    final MailboxSession mailboxSession = mailboxManager.loginAsOtherUser(authenticationAttempt.getAuthenticationId(),
                         authenticationAttempt.getPassword(),
-                        Username.of(authenticationAttempt.getDelegateUserName().get()));
+                        authenticationAttempt.getDelegateUserName().get());
                     session.authenticated();
                     session.setAttribute(ImapSessionUtils.MAILBOX_SESSION_ATTRIBUTE_SESSION_KEY, mailboxSession);
                     provisionInbox(session, mailboxManager, mailboxSession);
@@ -156,20 +156,20 @@ public abstract class AbstractAuthProcessor<R extends ImapRequest> extends Abstr
         }
     }
 
-    protected static AuthenticationAttempt delegation(String authorizeId, String authenticationId, String password) {
+    protected static AuthenticationAttempt delegation(Username authorizeId, Username authenticationId, String password) {
         return new AuthenticationAttempt(Optional.of(authorizeId), authenticationId, password);
     }
 
-    protected static AuthenticationAttempt noDelegation(String authenticationId, String password) {
+    protected static AuthenticationAttempt noDelegation(Username authenticationId, String password) {
         return new AuthenticationAttempt(Optional.empty(), authenticationId, password);
     }
 
     protected static class AuthenticationAttempt {
-        private final Optional<String> delegateUserName;
-        private final String authenticationId;
+        private final Optional<Username> delegateUserName;
+        private final Username authenticationId;
         private final String password;
 
-        public AuthenticationAttempt(Optional<String> delegateUserName, String authenticationId, String password) {
+        public AuthenticationAttempt(Optional<Username> delegateUserName, Username authenticationId, String password) {
             this.delegateUserName = delegateUserName;
             this.authenticationId = authenticationId;
             this.password = password;
@@ -179,11 +179,11 @@ public abstract class AbstractAuthProcessor<R extends ImapRequest> extends Abstr
             return delegateUserName.isPresent() && !delegateUserName.get().equals(authenticationId);
         }
 
-        public Optional<String> getDelegateUserName() {
+        public Optional<Username> getDelegateUserName() {
             return delegateUserName;
         }
 
-        public String getAuthenticationId() {
+        public Username getAuthenticationId() {
             return authenticationId;
         }
 
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AuthenticateProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AuthenticateProcessor.java
index b44dd1a..6a92f7c 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AuthenticateProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AuthenticateProcessor.java
@@ -26,6 +26,7 @@ import java.util.Base64;
 import java.util.List;
 import java.util.StringTokenizer;
 
+import org.apache.james.core.Username;
 import org.apache.james.imap.api.display.HumanReadableText;
 import org.apache.james.imap.api.message.request.ImapRequest;
 import org.apache.james.imap.api.message.response.StatusResponseFactory;
@@ -104,7 +105,7 @@ public class AuthenticateProcessor extends AbstractAuthProcessor<AuthenticateReq
             String token1 = authTokenizer.nextToken();  // Authorization Identity
             token2 = authTokenizer.nextToken();                 // Authentication Identity
             try {
-                return delegation(token1, token2, authTokenizer.nextToken());
+                return delegation(Username.of(token1), Username.of(token2), authTokenizer.nextToken());
             } catch (java.util.NoSuchElementException ignored) {
                 // If we got here, this is what happened.  RFC 2595
                 // says that "the client may leave the authorization
@@ -121,7 +122,7 @@ public class AuthenticateProcessor extends AbstractAuthProcessor<AuthenticateReq
                 // elements, leading to the exception we just
                 // caught.  So we need to move the user to the
                 // password, and the authorize_id to the user.
-                return noDelegation(token1, token2);
+                return noDelegation(Username.of(token1), token2);
             } finally {
                 authTokenizer = null;
             }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[james-project] 09/10: JAMES-2988 MessagePropertiesTest migration to Junit 5

Posted by rc...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rcordier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git

commit 6b2a542b8806fcb9f816b28b6e1d20822b69da2d
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Nov 21 15:23:40 2019 +0700

    JAMES-2988 MessagePropertiesTest migration to Junit 5
---
 .../james/jmap/draft/model/MessagePropertiesTest.java  | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java
index 6514f69..78bb1e7 100644
--- a/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java
+++ b/server/protocols/jmap-draft/src/test/java/org/apache/james/jmap/draft/model/MessagePropertiesTest.java
@@ -25,26 +25,26 @@ import java.util.Optional;
 
 import org.apache.james.jmap.draft.model.MessageProperties.HeaderProperty;
 import org.apache.james.jmap.draft.model.MessageProperties.MessageProperty;
-import org.junit.Test;
+import org.junit.jupiter.api.Test;
 
 import com.google.common.collect.ImmutableSet;
 
-public class MessagePropertiesTest {
+class MessagePropertiesTest {
 
     @Test
-    public void toOutputPropertiesShouldReturnAllMessagePropertiesWhenAbsent() {
+    void toOutputPropertiesShouldReturnAllMessagePropertiesWhenAbsent() {
         MessageProperties actual = new MessageProperties(Optional.empty()).toOutputProperties();
         assertThat(actual.getOptionalMessageProperties()).hasValue(MessageProperty.allOutputProperties());
     }
     
     @Test
-    public void toOutputPropertiesShouldReturnEmptyHeaderPropertiesWhenAbsent() {
+    void toOutputPropertiesShouldReturnEmptyHeaderPropertiesWhenAbsent() {
         MessageProperties actual = new MessageProperties(Optional.empty()).toOutputProperties();
         assertThat(actual.getOptionalHeadersProperties()).isEmpty();
     }
 
     @Test
-    public void toOutputPropertiesShouldReturnTextBodyWhenBodyRequested() {
+    void toOutputPropertiesShouldReturnTextBodyWhenBodyRequested() {
         MessageProperties actual = new MessageProperties(Optional.of(ImmutableSet.of("body"))).toOutputProperties();
         assertThat(actual.getOptionalMessageProperties())
             .hasValueSatisfying(value -> 
@@ -52,7 +52,7 @@ public class MessagePropertiesTest {
     }
 
     @Test
-    public void toOutputPropertiesShouldReturnIsUnread() {
+    void toOutputPropertiesShouldReturnIsUnread() {
         MessageProperties actual = new MessageProperties(Optional.of(ImmutableSet.of("isUnread"))).toOutputProperties();
         assertThat(actual.getOptionalMessageProperties())
                 .hasValueSatisfying(value ->
@@ -60,14 +60,14 @@ public class MessagePropertiesTest {
     }
 
     @Test
-    public void toOutputPropertiesShouldReturnMandatoryPropertiesWhenEmptyRequest() {
+    void toOutputPropertiesShouldReturnMandatoryPropertiesWhenEmptyRequest() {
         MessageProperties actual = new MessageProperties(Optional.of(ImmutableSet.of())).toOutputProperties();
         assertThat(actual.getOptionalMessageProperties())
             .hasValue(ImmutableSet.of(MessageProperty.id));
     }
 
     @Test
-    public void toOutputPropertiesShouldReturnAllHeadersWhenHeadersAndIndividualHeadersRequested() {
+    void toOutputPropertiesShouldReturnAllHeadersWhenHeadersAndIndividualHeadersRequested() {
         MessageProperties actual = new MessageProperties(
             Optional.of(ImmutableSet.of("headers.X-Spam-Score", "headers"))).toOutputProperties();
         assertThat(actual.getOptionalMessageProperties()).hasValueSatisfying(
@@ -77,7 +77,7 @@ public class MessagePropertiesTest {
     }
 
     @Test
-    public void toOutputPropertiesShouldReturnHeadersMessagePropertyWhenIndividualHeadersRequested() {
+    void toOutputPropertiesShouldReturnHeadersMessagePropertyWhenIndividualHeadersRequested() {
         MessageProperties actual = new MessageProperties(
             Optional.of(ImmutableSet.of("headers.X-Spam-Score"))).toOutputProperties();
         assertThat(actual.getOptionalMessageProperties()).hasValueSatisfying(


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org