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 672898bc579e876cb0705c8d713ee465822d91fb
Author: Benoit TELLIER <btell...@linagora.com>
AuthorDate: Fri Mar 22 11:43:04 2024 +0100

    JAMES-3977 Allow ChannelImapResponseWriter to work with sequence of bytes
    
    This allows accurate representation by the netty stack of the memory used.
---
 .../apache/james/mailbox/model/ByteContent.java    |  8 ++++++++
 .../org/apache/james/mailbox/model/Content.java    |  7 ++++++-
 .../mailbox/model/HeaderAndBodyByteContent.java    |  9 +++++++++
 .../jpa/mail/model/openjpa/JPAMailboxMessage.java  | 23 ++++++++++++++++++++++
 .../james/mailbox/store/MessageResultImpl.java     |  5 +++++
 .../store/mail/model/DelegatingMailboxMessage.java |  6 ++++++
 .../james/mailbox/store/mail/model/Message.java    | 12 +++++++++++
 .../store/mail/model/impl/SimpleMessage.java       |  6 ++++++
 .../store/streaming/InputStreamContent.java        | 12 ++++++++++-
 .../james/imap/message/BytesBackedLiteral.java     |  8 ++++++++
 .../org/apache/james/imap/message/Literal.java     |  5 +++++
 .../imap/processor/fetch/ContentBodyElement.java   |  7 ++++++-
 .../netty/ChannelImapResponseWriter.java           |  4 ++++
 13 files changed, 109 insertions(+), 3 deletions(-)

diff --git 
a/mailbox/api/src/main/java/org/apache/james/mailbox/model/ByteContent.java 
b/mailbox/api/src/main/java/org/apache/james/mailbox/model/ByteContent.java
index a14a7daa8a..f10f348c46 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/ByteContent.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/ByteContent.java
@@ -25,6 +25,7 @@ package org.apache.james.mailbox.model;
 import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
+import java.util.Optional;
 
 import org.reactivestreams.Publisher;
 
@@ -56,4 +57,11 @@ public final class ByteContent implements Content {
         return Flux.just(contents)
             .map(ByteBuffer::wrap);
     }
+
+    @Override
+    public Optional<byte[][]> asBytesSequence() {
+        byte[][] answer = new byte[1][];
+        answer[0] = contents;
+        return Optional.of(answer);
+    }
 }
diff --git 
a/mailbox/api/src/main/java/org/apache/james/mailbox/model/Content.java 
b/mailbox/api/src/main/java/org/apache/james/mailbox/model/Content.java
index abee852e0a..ef7a989fef 100644
--- a/mailbox/api/src/main/java/org/apache/james/mailbox/model/Content.java
+++ b/mailbox/api/src/main/java/org/apache/james/mailbox/model/Content.java
@@ -22,6 +22,7 @@ package org.apache.james.mailbox.model;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
+import java.util.Optional;
 
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.util.ReactorUtils;
@@ -41,7 +42,11 @@ public interface Content {
      * Return the content as {@link InputStream}
      */
     InputStream getInputStream() throws IOException;
-    
+
+    default Optional<byte[][]> asBytesSequence() {
+        return Optional.empty();
+    }
+
     /**
      * Size (in octets) of the content.
      * 
diff --git 
a/mailbox/api/src/main/java/org/apache/james/mailbox/model/HeaderAndBodyByteContent.java
 
b/mailbox/api/src/main/java/org/apache/james/mailbox/model/HeaderAndBodyByteContent.java
index bbd1740d6e..eb6c607c51 100644
--- 
a/mailbox/api/src/main/java/org/apache/james/mailbox/model/HeaderAndBodyByteContent.java
+++ 
b/mailbox/api/src/main/java/org/apache/james/mailbox/model/HeaderAndBodyByteContent.java
@@ -23,6 +23,7 @@ import java.io.ByteArrayInputStream;
 import java.io.InputStream;
 import java.io.SequenceInputStream;
 import java.nio.ByteBuffer;
+import java.util.Optional;
 
 import org.reactivestreams.Publisher;
 
@@ -53,6 +54,14 @@ public final class HeaderAndBodyByteContent implements 
Content {
             new ByteArrayInputStream(body));
     }
 
+    @Override
+    public Optional<byte[][]> asBytesSequence() {
+        byte[][] answer = new byte[2][];
+        answer[0] = headers;
+        answer[1] = body;
+        return Optional.of(answer);
+    }
+
     @Override
     public Publisher<ByteBuffer> reactiveBytes() {
         return Flux.concat(Flux.just(headers).map(ByteBuffer::wrap), 
Flux.just(body).map(ByteBuffer::wrap));
diff --git 
a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAMailboxMessage.java
 
b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAMailboxMessage.java
index 90dd699584..776cbef69e 100644
--- 
a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAMailboxMessage.java
+++ 
b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAMailboxMessage.java
@@ -22,6 +22,7 @@ import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Date;
+import java.util.Optional;
 
 import jakarta.mail.Flags;
 import jakarta.persistence.Basic;
@@ -123,4 +124,26 @@ public class JPAMailboxMessage extends 
AbstractJPAMailboxMessage {
     public MailboxMessage copy(Mailbox mailbox) throws MailboxException {
         return new JPAMailboxMessage(JPAMailbox.from(mailbox), getUid(), 
getModSeq(), this);
     }
+
+    @Override
+    public Optional<byte[][]> getBodyBytes() {
+        byte[][] answer = new byte[1][];
+        answer[0] = body;
+        return Optional.of(answer);
+    }
+
+    @Override
+    public Optional<byte[][]> getFullBytes() {
+        byte[][] answer = new byte[2][];
+        answer[0] = header;
+        answer[1] = body;
+        return Optional.of(answer);
+    }
+
+    @Override
+    public Optional<byte[][]> getHeadersBytes() {
+        byte[][] answer = new byte[1][];
+        answer[0] = header;
+        return Optional.of(answer);
+    }
 }
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 ce2a46cbb6..60a164e140 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
@@ -364,6 +364,11 @@ public class MessageResultImpl implements MessageResult {
             return msg.getHeaderOctets();
         }
 
+        @Override
+        public Optional<byte[][]> asBytesSequence() {
+            return msg.getHeadersBytes();
+        }
+
         @Override
         public Iterator<Header> headers() throws MailboxException {
             if (headers == null) {
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 c37516bbba..29726f4aa0 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
@@ -22,6 +22,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.util.Date;
 import java.util.List;
+import java.util.Optional;
 
 import jakarta.mail.Flags;
 
@@ -126,4 +127,9 @@ public abstract class DelegatingMailboxMessage implements 
MailboxMessage {
     public List<MessageAttachmentMetadata> getAttachments() {
         return message.getAttachments();
     }
+
+    @Override
+    public Optional<byte[][]> getFullBytes() {
+        return message.getFullBytes();
+    }
 }
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 a5f37bb198..bb45474030 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
@@ -25,6 +25,7 @@ import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.util.Date;
 import java.util.List;
+import java.util.Optional;
 
 import org.apache.james.mailbox.model.MessageAttachmentMetadata;
 import org.apache.james.mailbox.model.MessageId;
@@ -50,6 +51,10 @@ public interface Message {
      */
     InputStream getBodyContent() throws IOException;
 
+    default Optional<byte[][]> getBodyBytes() {
+        return Optional.empty();
+    }
+
     default Publisher<ByteBuffer> getBodyContentReactive() {
         try {
             return ReactorUtils.toChunks(getBodyContent(), BUFFER_SIZE)
@@ -103,6 +108,10 @@ public interface Message {
      */
     InputStream getHeaderContent() throws IOException;
 
+    default Optional<byte[][]> getHeadersBytes() {
+        return Optional.empty();
+    }
+
 
     default Publisher<ByteBuffer> getHeaderContentReactive() {
         try {
@@ -121,6 +130,9 @@ public interface Message {
      */
     InputStream getFullContent() throws IOException;
 
+    default Optional<byte[][]> getFullBytes() {
+        return Optional.empty();
+    }
 
     default Publisher<ByteBuffer> getFullContentReactive() {
         try {
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 add87a967d..ffe9b02ce2 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
@@ -23,6 +23,7 @@ import java.io.InputStream;
 import java.nio.ByteBuffer;
 import java.util.Date;
 import java.util.List;
+import java.util.Optional;
 
 import org.apache.commons.io.input.BoundedInputStream;
 import org.apache.james.mailbox.exception.MailboxException;
@@ -117,6 +118,11 @@ public class SimpleMessage implements Message {
         return content.getInputStream();
     }
 
+    @Override
+    public Optional<byte[][]> getFullBytes() {
+        return content.asBytesSequence();
+    }
+
     @Override
     public Properties getProperties() {
         return properties;
diff --git 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/streaming/InputStreamContent.java
 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/streaming/InputStreamContent.java
index 5a2662095a..92be0a277d 100644
--- 
a/mailbox/store/src/main/java/org/apache/james/mailbox/store/streaming/InputStreamContent.java
+++ 
b/mailbox/store/src/main/java/org/apache/james/mailbox/store/streaming/InputStreamContent.java
@@ -21,6 +21,7 @@ package org.apache.james.mailbox.store.streaming;
 import java.io.IOException;
 import java.io.InputStream;
 import java.nio.ByteBuffer;
+import java.util.Optional;
 
 import org.apache.james.mailbox.model.Content;
 import org.apache.james.mailbox.store.mail.model.Message;
@@ -64,7 +65,16 @@ public final class InputStreamContent implements Content {
         default:
             return m.getBodyContent();
         }
-       
+    }
+
+    @Override
+    public Optional<byte[][]> asBytesSequence() {
+        switch (type) {
+            case FULL:
+                return m.getFullBytes();
+            default:
+                return m.getBodyBytes();
+        }
     }
 
     @Override
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/message/BytesBackedLiteral.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/message/BytesBackedLiteral.java
index d5ff6b8b46..abca5df42a 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/message/BytesBackedLiteral.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/message/BytesBackedLiteral.java
@@ -22,6 +22,7 @@ package org.apache.james.imap.message;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Optional;
 
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream;
@@ -60,4 +61,11 @@ public class BytesBackedLiteral implements Literal {
     public InputStream getInputStream() {
         return new ByteArrayInputStream(content);
     }
+
+    @Override
+    public Optional<byte[][]> asBytesSequence() {
+        byte[][] answer = new byte[1][];
+        answer[0] = content;
+        return Optional.of(answer);
+    }
 }
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/message/Literal.java 
b/protocols/imap/src/main/java/org/apache/james/imap/message/Literal.java
index 94851f07f7..9ef6fba741 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/message/Literal.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/message/Literal.java
@@ -21,6 +21,7 @@ package org.apache.james.imap.message;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Optional;
 
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.model.Content;
@@ -42,6 +43,10 @@ public interface Literal {
      */
     InputStream getInputStream() throws IOException;
 
+    default Optional<byte[][]> asBytesSequence() {
+        return Optional.empty();
+    }
+
     default Content asMailboxContent() {
         Literal literal = this;
         return new Content() {
diff --git 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/ContentBodyElement.java
 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/ContentBodyElement.java
index 5cbf722047..1aef078f8f 100644
--- 
a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/ContentBodyElement.java
+++ 
b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/ContentBodyElement.java
@@ -24,6 +24,7 @@ package org.apache.james.imap.processor.fetch;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.util.Optional;
 
 import org.apache.james.imap.message.response.FetchResponse.BodyElement;
 import org.apache.james.mailbox.exception.MailboxException;
@@ -51,7 +52,11 @@ class ContentBodyElement implements BodyElement {
             throw new IOException("Unable to get size for body element", e);
         }
     }
-
+    
+    @Override
+    public Optional<byte[][]> asBytesSequence() {
+        return content.asBytesSequence();
+    }
 
     @Override
     public InputStream getInputStream() throws IOException {
diff --git 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
index 0a4f53ce9c..55734944b8 100644
--- 
a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
+++ 
b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ChannelImapResponseWriter.java
@@ -77,6 +77,10 @@ public class ChannelImapResponseWriter implements 
ImapResponseWriter {
     public void write(Literal literal) throws IOException {
         flushCallback.run();
         if (channel.isActive()) {
+            if (literal.asBytesSequence().isPresent()) {
+                
channel.writeAndFlush(Unpooled.wrappedBuffer(literal.asBytesSequence().get()));
+                return;
+            }
             InputStream in = literal.getInputStream();
             if (in instanceof FileInputStream) {
                 FileChannel fc = ((FileInputStream) in).getChannel();


---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org
For additional commands, e-mail: notifications-h...@james.apache.org

Reply via email to