Merge pull request #678 from garyrussell/INT-2821

* INT-2821: Find Existing Mails if No RECENT Support
This commit is contained in:
Mark Fisher
2012-11-20 17:02:53 -05:00
2 changed files with 163 additions and 0 deletions

View File

@@ -110,6 +110,11 @@ public class ImapMailReceiver extends AbstractMailReceiver {
if (imapFolder.hasNewMessages()) {
return;
}
else if (!folder.getPermanentFlags().contains(Flags.Flag.RECENT)) {
if (searchForNewMessages().length > 0) {
return;
}
}
imapFolder.addMessageCountListener(this.messageCountListener);
try {
imapFolder.idle();

View File

@@ -17,7 +17,9 @@ package org.springframework.integration.mail;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -29,6 +31,8 @@ import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
@@ -409,6 +413,160 @@ public class ImapMailReceiverTests {
assertEquals("Failed", ((Exception) replMessage.getPayload()).getCause().getMessage());
}
@Test
public void testNoInitialIdleDelayWhenRecentNotSupported() throws Exception{
ApplicationContext context =
new ClassPathXmlApplicationContext("ImapIdleChannelAdapterParserTests-context.xml", ImapIdleChannelAdapterParserTests.class);
ImapIdleChannelAdapter adapter = context.getBean("simpleAdapter", ImapIdleChannelAdapter.class);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
ImapMailReceiver receiver = new ImapMailReceiver("imap:foo");
receiver = spy(receiver);
receiver.afterPropertiesSet();
final IMAPFolder folder = mock(IMAPFolder.class);
when(folder.getPermanentFlags()).thenReturn(new Flags(Flags.Flag.USER));
when(folder.isOpen()).thenReturn(false).thenReturn(true);
when(folder.exists()).thenReturn(true);
DirectFieldAccessor adapterAccessor = new DirectFieldAccessor(adapter);
adapterAccessor.setPropertyValue("mailReceiver", receiver);
Field storeField = AbstractMailReceiver.class.getDeclaredField("store");
storeField.setAccessible(true);
Store store = mock(Store.class);
when(store.isConnected()).thenReturn(true);
when(store.getFolder(Mockito.any(URLName.class))).thenReturn(folder);
storeField.set(receiver, store);
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
return folder;
}
}).when(receiver).getFolder();
MimeMessage mailMessage = mock(MimeMessage.class);
Flags flags = mock(Flags.class);
when(mailMessage.getFlags()).thenReturn(flags);
final Message[] messages = new Message[]{mailMessage};
final AtomicInteger shouldFindMessagesCounter = new AtomicInteger(2);
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
/*
* Return the message from first invocation of waitForMessages()
* and in receive(); then return false in the next call to
* waitForMessages() so we enter idle(); counter will be reset
* to 1 in the mocked idle().
*/
if (shouldFindMessagesCounter.decrementAndGet() >= 0) {
return messages;
}
else {
return new Message[0];
}
}
}).when(receiver).searchForNewMessages();
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
return null;
}
}).when(receiver).fetchMessages(messages);
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
Thread.sleep(5000);
shouldFindMessagesCounter.set(1);
return null;
}
}).when(folder).idle();
adapter.start();
/*
* Idle takes 5 seconds; if all is well, we should receive the first message
* before then.
*/
assertNotNull(channel.receive(3000));
// We should not receive any more until the next idle elapses
assertNull(channel.receive(3000));
assertNotNull(channel.receive(6000));
}
@Test
public void testInitialIdleDelayWhenRecentIsSupported() throws Exception{
ApplicationContext context =
new ClassPathXmlApplicationContext("ImapIdleChannelAdapterParserTests-context.xml", ImapIdleChannelAdapterParserTests.class);
ImapIdleChannelAdapter adapter = context.getBean("simpleAdapter", ImapIdleChannelAdapter.class);
QueueChannel channel = new QueueChannel();
adapter.setOutputChannel(channel);
ImapMailReceiver receiver = new ImapMailReceiver("imap:foo");
receiver = spy(receiver);
receiver.afterPropertiesSet();
final IMAPFolder folder = mock(IMAPFolder.class);
when(folder.getPermanentFlags()).thenReturn(new Flags(Flags.Flag.RECENT));
when(folder.isOpen()).thenReturn(false).thenReturn(true);
when(folder.exists()).thenReturn(true);
DirectFieldAccessor adapterAccessor = new DirectFieldAccessor(adapter);
adapterAccessor.setPropertyValue("mailReceiver", receiver);
Field storeField = AbstractMailReceiver.class.getDeclaredField("store");
storeField.setAccessible(true);
Store store = mock(Store.class);
when(store.isConnected()).thenReturn(true);
when(store.getFolder(Mockito.any(URLName.class))).thenReturn(folder);
storeField.set(receiver, store);
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
return folder;
}
}).when(receiver).getFolder();
MimeMessage mailMessage = mock(MimeMessage.class);
Flags flags = mock(Flags.class);
when(mailMessage.getFlags()).thenReturn(flags);
final Message[] messages = new Message[]{mailMessage};
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
return messages;
}
}).when(receiver).searchForNewMessages();
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
return null;
}
}).when(receiver).fetchMessages(messages);
final CountDownLatch idles = new CountDownLatch(2);
doAnswer(new Answer<Object>() {
public Object answer(InvocationOnMock invocation) throws Throwable {
idles.countDown();
Thread.sleep(5000);
return null;
}
}).when(folder).idle();
adapter.start();
/*
* Idle takes 5 seconds; since this server supports RECENT, we should
* not receive any early messages.
*/
assertNull(channel.receive(3000));
assertNotNull(channel.receive(5000));
assertTrue(idles.await(5, TimeUnit.SECONDS));
}
@Test // see INT-1801
public void testImapLifecycleForRaceCondition() throws Exception{