This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 1fb2e4b4f784bbe8c1e21c7c73e4a2bcbc920337 Author: Benoit TELLIER <btell...@linagora.com> AuthorDate: Tue Feb 27 10:34:11 2024 +0100 JAMES-4007 Manage IMAP litteral with Leak aware --- .../imapserver/netty/ImapRequestFrameDecoder.java | 52 ++++++++++++++++++---- .../netty/NettyStreamImapRequestLineReader.java | 18 ++++---- 2 files changed, 51 insertions(+), 19 deletions(-) diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java index 4f9fd126a8..fbd8930423 100644 --- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java +++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/ImapRequestFrameDecoder.java @@ -36,6 +36,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; import java.util.function.Consumer; +import org.apache.commons.io.FileUtils; import org.apache.commons.lang3.tuple.Pair; import org.apache.james.imap.api.ImapMessage; import org.apache.james.imap.api.ImapSessionState; @@ -43,6 +44,7 @@ import org.apache.james.imap.api.process.ImapSession; import org.apache.james.imap.decode.DecodingException; import org.apache.james.imap.decode.ImapDecoder; import org.apache.james.imap.decode.ImapRequestLineReader; +import org.apache.james.lifecycle.api.Disposable.LeakAware; import org.apache.james.protocols.netty.LineHandlerAware; import com.github.fge.lambdas.Throwing; @@ -230,10 +232,7 @@ public class ImapRequestFrameDecoder extends ByteToMessageDecoder implements Net // Not doing this causes IDLEd IMAP connections to clear IMAP append literal while they are processed. attachment.remove(SUBSCRIPTION); parseImapMessage(ctx, null, attachment, Pair.of(reader, size), readerIndex) - .ifPresent(message -> { - - ctx.fireChannelRead(message); - }); + .ifPresent(ctx::fireChannelRead); } catch (DecodingException e) { ctx.fireExceptionCaught(e); } @@ -253,18 +252,53 @@ public class ImapRequestFrameDecoder extends ByteToMessageDecoder implements Net } } + public static class FileHolderInner extends LeakAware.Resource { + public static FileHolderInner create() throws IOException { + return new FileHolderInner(Files.createTempFile("imap-literal", ".tmp").toFile()); + } + + private final File file; + + private FileHolderInner(File file) { + super(() -> FileUtils.deleteQuietly(file)); + this.file = file; + } + + public File getFile() { + return file; + } + } + + public static class FileHolder extends LeakAware<FileHolderInner> { + public static FileHolder create() throws IOException { + return new FileHolder(FileHolderInner.create()); + } + + private final FileHolderInner file; + + private FileHolder(FileHolderInner file) { + super(file); + this.file = file; + } + + public File getFile() { + return file.file; + } + + } + static class FileChunkConsumer implements Consumer<byte[]> { private final int size; private final AtomicInteger written = new AtomicInteger(0); private final AtomicBoolean initialized = new AtomicBoolean(false); private OutputStream outputStream; - private File file; + private FileHolder file; FileChunkConsumer(int size) { this.size = size; } - public File getFile() { + public FileHolder getFile() { return file; } @@ -279,8 +313,8 @@ public class ImapRequestFrameDecoder extends ByteToMessageDecoder implements Net private void initialize() { try { - file = Files.createTempFile("imap-literal", ".tmp").toFile(); - outputStream = new FileOutputStream(file, true); + file = FileHolder.create(); + outputStream = new FileOutputStream(file.getFile(), true); initialized.set(true); } catch (IOException e) { throw new RuntimeException(e); @@ -318,7 +352,7 @@ public class ImapRequestFrameDecoder extends ByteToMessageDecoder implements Net outputStream.close(); } if (file != null) { - Files.delete(file.toPath()); + file.dispose(); } })).subscribeOn(Schedulers.boundedElastic()) .subscribe(); diff --git a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/NettyStreamImapRequestLineReader.java b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/NettyStreamImapRequestLineReader.java index e567013f86..ee3d533a21 100644 --- a/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/NettyStreamImapRequestLineReader.java +++ b/server/protocols/protocols-imap4/src/main/java/org/apache/james/imapserver/netty/NettyStreamImapRequestLineReader.java @@ -19,13 +19,11 @@ package org.apache.james.imapserver.netty; import java.io.Closeable; -import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; -import org.apache.commons.io.FileUtils; import org.apache.james.imap.api.display.HumanReadableText; import org.apache.james.imap.decode.DecodingException; import org.apache.james.imap.message.Literal; @@ -44,10 +42,10 @@ public class NettyStreamImapRequestLineReader extends AbstractNettyImapRequestLi private final long offset; private final int size; private final boolean extraCRLF; - private final File file; + private final ImapRequestFrameDecoder.FileHolder file; private final AbstractNettyImapRequestLineReader reader; - private FileLiteral(long offset, int size, boolean extraCRLF, File file, AbstractNettyImapRequestLineReader reader) { + private FileLiteral(long offset, int size, boolean extraCRLF, ImapRequestFrameDecoder.FileHolder file, AbstractNettyImapRequestLineReader reader) { this.offset = offset; this.size = size; this.extraCRLF = extraCRLF; @@ -57,19 +55,19 @@ public class NettyStreamImapRequestLineReader extends AbstractNettyImapRequestLi @Override public void close() { - Mono.fromRunnable(Throwing.runnable(() -> FileUtils.deleteQuietly(file))) + Mono.fromRunnable(Throwing.runnable(() -> file.dispose())) .subscribeOn(Schedulers.boundedElastic()) .subscribe(); } @Override public long size() { - return Math.min(file.length() - offset, size); + return Math.min(file.getFile().length() - offset, size); } @Override public InputStream getInputStream() throws IOException { - FileInputStream fileInputStream = new FileInputStream(file); + FileInputStream fileInputStream = new FileInputStream(file.getFile()); fileInputStream.skip(offset); InputStream limitedStream = ByteStreams.limit(fileInputStream, size); if (extraCRLF) { @@ -80,14 +78,14 @@ public class NettyStreamImapRequestLineReader extends AbstractNettyImapRequestLi } } - private final File backingFile; + private final ImapRequestFrameDecoder.FileHolder backingFile; private final CountingInputStream in; - public NettyStreamImapRequestLineReader(Channel channel, File file, boolean retry) { + public NettyStreamImapRequestLineReader(Channel channel, ImapRequestFrameDecoder.FileHolder file, boolean retry) { super(channel, retry); this.backingFile = file; try { - this.in = new CountingInputStream(new FileInputStream(file)); + this.in = new CountingInputStream(new FileInputStream(file.getFile())); } catch (FileNotFoundException e) { throw new RuntimeException(e); } --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org