From 658572ea4495affab8db7567f625a31651093b3b Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Sat, 28 Aug 2010 14:47:54 +0000 Subject: [PATCH] INT-1375, INT-1376, Added support for Flags.SEEN. Added namespace support for should-mark-messages-as-read for IMAP idle, test cases --- .../mail/AbstractMailReceiver.java | 15 ++--- .../config/ImapIdleChannelAdapterParser.java | 2 + .../MailInboundChannelAdapterParser.java | 2 + .../mail/config/MailReceiverFactoryBean.java | 19 +++++++ .../config/spring-integration-mail-2.0.xsd | 9 ++- .../mail/AbstractMailReceiverTests.java | 55 ++++++++++++------- ...pIdleChannelAdapterParserTests-context.xml | 7 +++ .../ImapIdleChannelAdapterParserTests.java | 21 +++++++ ...boundChannelAdapterParserTests-context.xml | 2 + .../InboundChannelAdapterParserTests.java | 9 +++ 10 files changed, 113 insertions(+), 28 deletions(-) diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/AbstractMailReceiver.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/AbstractMailReceiver.java index 3b89672fce..2aafdc86a7 100755 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/AbstractMailReceiver.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/AbstractMailReceiver.java @@ -147,19 +147,20 @@ public abstract class AbstractMailReceiver implements MailReceiver, DisposableBe * Specify whether mail messages should be deleted after retrieval. */ public void setShouldDeleteMessages(boolean shouldDeleteMessages) { - if (this.shouldMarkMessagesAsRead && shouldDeleteMessages){ - throw new IllegalArgumentException("setting both 'shouldDeleteMessages' and 'shouldMarkMessagesAsRead' to true is not allowed"); - } this.shouldDeleteMessages = shouldDeleteMessages; } + /** + * Check if messages should be marked as read + * @return + */ public boolean isShouldMarkMessagesAsRead() { return shouldMarkMessagesAsRead; } - + /** + * Specify is messages should be marked as read + * @return + */ public void setShouldMarkMessagesAsRead(boolean shouldMarkMessagesAsRead) { - if (this.shouldDeleteMessages && shouldMarkMessagesAsRead){ - throw new IllegalArgumentException("setting both 'shouldDeleteMessages' and 'shouldMarkMessagesAsRead' to true is not allowed"); - } this.shouldMarkMessagesAsRead = shouldMarkMessagesAsRead; } diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParser.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParser.java index 8afa6c3e2c..607581bf46 100644 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParser.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParser.java @@ -31,6 +31,7 @@ import org.springframework.util.StringUtils; * * @author Jonas Partner * @author Mark Fisher + * @author Oleg Zhurakousky */ public class ImapIdleChannelAdapterParser extends AbstractSingleBeanDefinitionParser { @@ -79,6 +80,7 @@ public class ImapIdleChannelAdapterParser extends AbstractSingleBeanDefinitionPa } IntegrationNamespaceUtils.setValueIfAttributeDefined(receiverBuilder, element, "max-fetch-size"); receiverBuilder.addPropertyValue("shouldDeleteMessages", element.getAttribute("should-delete-messages")); + receiverBuilder.addPropertyValue("shouldMarkMessagesAsRead", element.getAttribute("should-mark-messages-as-read")); return receiverBuilder.getBeanDefinition(); } diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailInboundChannelAdapterParser.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailInboundChannelAdapterParser.java index 53c3d85f69..7f717f7ad7 100644 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailInboundChannelAdapterParser.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailInboundChannelAdapterParser.java @@ -33,6 +33,7 @@ import org.springframework.util.xml.DomUtils; * * @author Jonas Partner * @author Mark Fisher + * @author Oleg Zhurakousky */ public class MailInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser { @@ -80,6 +81,7 @@ public class MailInboundChannelAdapterParser extends AbstractPollingInboundChann } } receiverBuilder.addPropertyValue("shouldDeleteMessages", element.getAttribute("should-delete-messages")); + receiverBuilder.addPropertyValue("shouldMarkMessagesAsRead", element.getAttribute("should-mark-messages-as-read")); return receiverBuilder.getBeanDefinition(); } diff --git a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailReceiverFactoryBean.java b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailReceiverFactoryBean.java index c824481d6e..bf3cba56ca 100644 --- a/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailReceiverFactoryBean.java +++ b/spring-integration-mail/src/main/java/org/springframework/integration/mail/config/MailReceiverFactoryBean.java @@ -22,6 +22,8 @@ import javax.mail.Authenticator; import javax.mail.Session; import javax.mail.URLName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.FactoryBean; import org.springframework.integration.mail.AbstractMailReceiver; @@ -33,9 +35,11 @@ import org.springframework.util.StringUtils; /** * @author Mark Fisher + * @author Oleg Zhurakousky * @since 1.0.3 */ public class MailReceiverFactoryBean implements FactoryBean, DisposableBean { + protected final Log logger = LogFactory.getLog(this.getClass()); private volatile String storeUri; @@ -54,6 +58,8 @@ public class MailReceiverFactoryBean implements FactoryBean, Dispo * This value will be null unless explicitly configured. */ private volatile Boolean shouldDeleteMessages = null; + + private volatile boolean shouldMarkMessagesAsRead; private volatile int maxFetchSize = 1; @@ -141,6 +147,11 @@ public class MailReceiverFactoryBean implements FactoryBean, Dispo receiver.setShouldDeleteMessages(this.shouldDeleteMessages); } receiver.setMaxFetchSize(this.maxFetchSize); + if (isPop3 && this.shouldMarkMessagesAsRead){ + logger.warn("Setting 'should-mark-messages-as-read' to 'true' while using POP3 has no effect"); + } else { + receiver.setShouldMarkMessagesAsRead(this.shouldMarkMessagesAsRead); + } return receiver; } @@ -149,5 +160,13 @@ public class MailReceiverFactoryBean implements FactoryBean, Dispo ((DisposableBean) this.receiver).destroy(); } } + + public boolean isShouldMarkMessagesAsRead() { + return shouldMarkMessagesAsRead; + } + + public void setShouldMarkMessagesAsRead(boolean shouldMarkMessagesAsRead) { + this.shouldMarkMessagesAsRead = shouldMarkMessagesAsRead; + } } diff --git a/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.0.xsd b/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.0.xsd index 2745915985..f1167a2cff 100644 --- a/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.0.xsd +++ b/spring-integration-mail/src/main/resources/org/springframework/integration/mail/config/spring-integration-mail-2.0.xsd @@ -188,13 +188,20 @@ ]]> - + + + + + + diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/AbstractMailReceiverTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/AbstractMailReceiverTests.java index b0b5a032d4..5993ebc710 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/AbstractMailReceiverTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/AbstractMailReceiverTests.java @@ -20,6 +20,7 @@ import javax.mail.Flags.Flag; import javax.mail.internet.MimeMessage; import org.junit.Test; +import org.mockito.Mockito; import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; @@ -34,28 +35,9 @@ import static org.mockito.Mockito.verify; * */ public class AbstractMailReceiverTests { - - @Test(expected=IllegalArgumentException.class) - public void validateDeleteAndReadIsNotAllowed(){ - AbstractMailReceiver receiver = new ImapMailReceiver(); - receiver.setShouldDeleteMessages(true); - receiver.setShouldMarkMessagesAsRead(true); - } - @Test - public void validateDeleteOrReadIsAllowed_Read(){ - AbstractMailReceiver receiver = new ImapMailReceiver(); - receiver.setShouldDeleteMessages(false); - receiver.setShouldMarkMessagesAsRead(true); - } - @Test - public void validateDeleteOrReadIsAllowed_Delete(){ - AbstractMailReceiver receiver = new ImapMailReceiver(); - receiver.setShouldDeleteMessages(true); - receiver.setShouldMarkMessagesAsRead(false); - } @Test - public void receieveAndMarkAsRead() throws Exception{ + public void receieveAndMarkAsReadDontDelete() throws Exception{ AbstractMailReceiver receiver = new ImapMailReceiver(); receiver.setShouldMarkMessagesAsRead(true); receiver = spy(receiver); @@ -83,6 +65,39 @@ public class AbstractMailReceiverTests { receiver.receive(); verify(msg1, times(1)).setFlag(Flag.SEEN, true); verify(msg2, times(1)).setFlag(Flag.SEEN, true); + verify(receiver, times(0)).deleteMessages((Message[]) Mockito.any()); + } + @Test + public void receieveMarkAsReadAndDelete() throws Exception{ + AbstractMailReceiver receiver = new ImapMailReceiver(); + receiver.setShouldMarkMessagesAsRead(true); + receiver.setShouldDeleteMessages(true); + receiver = spy(receiver); + Message msg1 = mock(MimeMessage.class); + Message msg2 = mock(MimeMessage.class); + final Message[] messages = new Message[]{msg1, msg2}; + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + // just to avoid the exception + return null; + } + }).when(receiver).openFolder(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return messages; + } + }).when(receiver).searchForNewMessages(); + + doAnswer(new Answer() { + public Object answer(InvocationOnMock invocation) throws Throwable { + return null; + } + }).when(receiver).fetchMessages(messages); + receiver.receive(); + verify(msg1, times(1)).setFlag(Flag.SEEN, true); + verify(msg2, times(1)).setFlag(Flag.SEEN, true); + verify(receiver, times(1)).deleteMessages((Message[]) Mockito.any()); } @Test public void receieveAndDontMarkAsRead() throws Exception{ diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParserTests-context.xml b/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParserTests-context.xml index 75385ccef5..7c4d050f99 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParserTests-context.xml +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/ImapIdleChannelAdapterParserTests-context.xml @@ -32,6 +32,13 @@ channel="channel" auto-startup="false" should-delete-messages="true"/> + + + + diff --git a/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/InboundChannelAdapterParserTests.java b/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/InboundChannelAdapterParserTests.java index 7fdacb6a03..4aafc8778a 100644 --- a/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/InboundChannelAdapterParserTests.java +++ b/spring-integration-mail/src/test/java/org/springframework/integration/mail/config/InboundChannelAdapterParserTests.java @@ -43,6 +43,7 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; /** * @author Mark Fisher + * @author Oleg Zhurakousky * @since 1.0.5 */ @ContextConfiguration @@ -62,6 +63,14 @@ public class InboundChannelAdapterParserTests { Boolean value = (Boolean) new DirectFieldAccessor(receiver).getPropertyValue("shouldDeleteMessages"); assertTrue(value); } + + @Test + public void pop3ShouldMarkMessagesAsRead() { + AbstractMailReceiver receiver = this.getReceiver("pop3ShouldMarkAsReadTrue"); + assertEquals(Pop3MailReceiver.class, receiver.getClass()); + Boolean value = (Boolean) new DirectFieldAccessor(receiver).getPropertyValue("shouldMarkMessagesAsRead"); + assertFalse(value); + } @Test public void pop3ShouldDeleteFalse() {