diff --git a/greenmail-core/pom.xml b/greenmail-core/pom.xml
index e9d8e2ab82..cff7efa2cc 100644
--- a/greenmail-core/pom.xml
+++ b/greenmail-core/pom.xml
@@ -61,6 +61,21 @@
org.hamcrest
hamcrest-all
+
+ org.easymock
+ easymock
+ test
+
+
+ org.powermock
+ powermock-module-junit4
+ test
+
+
+ org.powermock
+ powermock-api-easymock
+ test
+
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/Managers.java b/greenmail-core/src/main/java/com/icegreen/greenmail/Managers.java
index c70f1470a1..47ee069037 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/Managers.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/Managers.java
@@ -8,6 +8,7 @@
import com.icegreen.greenmail.imap.ImapHostManagerImpl;
import com.icegreen.greenmail.smtp.SmtpManager;
import com.icegreen.greenmail.store.InMemoryStore;
+import com.icegreen.greenmail.store.Store;
import com.icegreen.greenmail.user.UserManager;
/**
@@ -16,19 +17,39 @@
* @since Jan 27, 2006
*/
public class Managers {
- private ImapHostManager imapHostManager = new ImapHostManagerImpl(new InMemoryStore());
- private UserManager userManager = new UserManager(imapHostManager);
- private SmtpManager smtpManager = new SmtpManager(imapHostManager, userManager);
+ private ImapHostManager imapHostManager;
+ private UserManager userManager;
+ private SmtpManager smtpManager;
- public SmtpManager getSmtpManager() {
+ public Managers() {
+ this(new InMemoryStore());
+ }
+
+ protected Managers(final Store imapHostManagerStore) {
+ imapHostManager = new ImapHostManagerImpl(imapHostManagerStore);
+ userManager = new UserManager(imapHostManager);
+ smtpManager = new SmtpManager(imapHostManager, userManager);
+ }
+
+ public final SmtpManager getSmtpManager() {
return smtpManager;
}
- public UserManager getUserManager() {
+ public final UserManager getUserManager() {
return userManager;
}
- public ImapHostManager getImapHostManager() {
+ public final ImapHostManager getImapHostManager() {
return imapHostManager;
}
+
+ public final void reset() {
+ imapHostManager = new ImapHostManagerImpl(createNewStore());
+ userManager = new UserManager(imapHostManager);
+ smtpManager = new SmtpManager(imapHostManager, userManager);
+ }
+
+ protected Store createNewStore() {
+ return new InMemoryStore();
+ }
}
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/MemorySafeManagers.java b/greenmail-core/src/main/java/com/icegreen/greenmail/MemorySafeManagers.java
new file mode 100644
index 0000000000..2f31616ac9
--- /dev/null
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/MemorySafeManagers.java
@@ -0,0 +1,29 @@
+/*
+ * -------------------------------------------------------------------
+ * This software is released under the Apache license 2.0
+ * -------------------------------------------------------------------
+ * /
+ */
+
+package com.icegreen.greenmail;
+
+import com.icegreen.greenmail.store.InMemoryStore;
+import com.icegreen.greenmail.store.Store;
+import com.icegreen.greenmail.store.StoredMessageCollectionFactory;
+
+/**
+ * {@link Managers} which uses the {@link StoredMessageCollectionFactory#MAP_BASED_FACTORY MAP_BASED_FACTORY} for
+ * instantiating the {@link InMemoryStore}.
+ *
+ * @author Raimund Klein
+ */
+public class MemorySafeManagers extends Managers {
+ public MemorySafeManagers() {
+ super(new InMemoryStore(StoredMessageCollectionFactory.MAP_BASED_FACTORY));
+ }
+
+ @Override
+ protected Store createNewStore() {
+ return new InMemoryStore(StoredMessageCollectionFactory.MAP_BASED_FACTORY);
+ }
+}
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/configuration/ConfiguredGreenMail.java b/greenmail-core/src/main/java/com/icegreen/greenmail/configuration/ConfiguredGreenMail.java
index b01b64dee1..5020fa79ca 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/configuration/ConfiguredGreenMail.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/configuration/ConfiguredGreenMail.java
@@ -1,13 +1,36 @@
package com.icegreen.greenmail.configuration;
+import com.icegreen.greenmail.Managers;
import com.icegreen.greenmail.base.GreenMailOperations;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* A version of GreenMailOperations that implements the configure() method.
*/
public abstract class ConfiguredGreenMail implements GreenMailOperations {
+ protected final Logger log = LoggerFactory.getLogger(getClass());
private GreenMailConfiguration config;
+ protected final Managers createManagers() {
+ if (config == null)
+ config = GreenMailConfiguration.aConfig();
+ Class extends Managers> configuredManagersClass = config.getManagersClass();
+ try {
+ return configuredManagersClass.newInstance();
+ } catch (InstantiationException e) {
+ log.warn(String.format("Could not instantiate Managers class '%s'. Will run with default class '%s'.",
+ configuredManagersClass, Managers.class), e);
+ } catch (IllegalAccessException e) {
+ log.warn(String.format("Illegal access while instantiating Managers class '%s'. Will run with default " +
+ "class '%s'.", configuredManagersClass, Managers.class), e);
+ } catch (Exception e) {
+ log.warn(String.format("General exception while instantiating Managers class '%s'. Will run with default " +
+ "class '%s'.", configuredManagersClass, Managers.class), e);
+ }
+ return new Managers();
+ }
+
@Override
public ConfiguredGreenMail withConfiguration(GreenMailConfiguration config) {
this.config = config;
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/configuration/GreenMailConfiguration.java b/greenmail-core/src/main/java/com/icegreen/greenmail/configuration/GreenMailConfiguration.java
index ad6fbf1519..9381dfabfd 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/configuration/GreenMailConfiguration.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/configuration/GreenMailConfiguration.java
@@ -1,5 +1,7 @@
package com.icegreen.greenmail.configuration;
+import com.icegreen.greenmail.Managers;
+
import java.util.ArrayList;
import java.util.List;
@@ -8,6 +10,14 @@
*/
public class GreenMailConfiguration {
private final List usersToCreate = new ArrayList();
+ private Class extends Managers> managersClass = Managers.class;
+
+ /**
+ * @return New GreenMail configuration
+ */
+ public static GreenMailConfiguration aConfig() {
+ return new GreenMailConfiguration();
+ }
/**
* The given {@link com.icegreen.greenmail.user.GreenMailUser} will be created when servers will start
@@ -33,11 +43,12 @@ public GreenMailConfiguration withUser(final String email, final String login, f
return this;
}
- /**
- * @return New GreenMail configuration
- */
- public static GreenMailConfiguration aConfig() {
- return new GreenMailConfiguration();
+ public GreenMailConfiguration withManagersClass(final Class extends Managers> managersClass) {
+ if (managersClass == null) {
+ throw new NullPointerException("managersClass may not be null.");
+ }
+ this.managersClass = managersClass;
+ return this;
}
/**
@@ -46,4 +57,11 @@ public static GreenMailConfiguration aConfig() {
public List getUsersToCreate() {
return usersToCreate;
}
+
+ /**
+ * @return The {@link Managers} class to should be used
+ */
+ public Class extends Managers> getManagersClass() {
+ return managersClass;
+ }
}
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/ImapHostManagerImpl.java b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/ImapHostManagerImpl.java
index 172ce3bc09..5c82fc722d 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/imap/ImapHostManagerImpl.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/imap/ImapHostManagerImpl.java
@@ -28,8 +28,7 @@ public class ImapHostManagerImpl
* Hack constructor which creates an in-memory store, and creates a console logger.
*/
public ImapHostManagerImpl() {
- store = new InMemoryStore();
- subscriptions = new MailboxSubscriptions();
+ this(new InMemoryStore());
}
public ImapHostManagerImpl(Store store) {
@@ -294,6 +293,10 @@ private String getQualifiedMailboxName(GreenMailUser user, String mailboxName) {
}
}
+ public Store getStore() {
+ return store;
+ }
+
/**
* Handles all user subscriptions.
* TODO make this a proper class
@@ -348,9 +351,4 @@ private List getUserSubs(GreenMailUser user) {
return subs;
}
}
-
- @Override
- public Store getStore() {
- return store;
- }
}
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/mail/MovingMessage.java b/greenmail-core/src/main/java/com/icegreen/greenmail/mail/MovingMessage.java
index fbbfd15d04..cc1e748b02 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/mail/MovingMessage.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/mail/MovingMessage.java
@@ -37,14 +37,14 @@ public class MovingMessage {
private MimeMessage message;
private int _references = 0;
- public List getToAddresses() {
- return toAddresses;
- }
-
public MovingMessage(Workspace workspace) {
_workspace = workspace;
}
+ public List getToAddresses() {
+ return toAddresses;
+ }
+
public MimeMessage getMessage() {
return message;
}
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/server/AbstractServer.java b/greenmail-core/src/main/java/com/icegreen/greenmail/server/AbstractServer.java
index 815cfc75e5..f3076b3682 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/server/AbstractServer.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/server/AbstractServer.java
@@ -26,13 +26,13 @@
public abstract class AbstractServer extends Thread implements Service {
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final InetAddress bindTo;
+ private final List handlers = Collections.synchronizedList(new ArrayList());
+ private final Object startupMonitor = new Object();
protected ServerSocket serverSocket = null;
protected Managers managers;
protected ServerSetup setup;
- private final List handlers = Collections.synchronizedList(new ArrayList());
private volatile boolean keepRunning = false;
private volatile boolean running = false;
- private final Object startupMonitor = new Object();
protected AbstractServer(ServerSetup setup, Managers managers) {
this.setup = setup;
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/store/HierarchicalFolder.java b/greenmail-core/src/main/java/com/icegreen/greenmail/store/HierarchicalFolder.java
index 8dbc2bdb7f..f5006bdc82 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/store/HierarchicalFolder.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/store/HierarchicalFolder.java
@@ -30,7 +30,8 @@ class HierarchicalFolder implements MailFolder, UIDFolder {
PERMANENT_FLAGS.add(Flags.Flag.SEEN);
}
- private final StoredMessageCollection mailMessages = new ListBasedStoredMessageCollection();
+ private final StoredMessageCollectionFactory storedMessageCollectionFactory;
+ private final StoredMessageCollection mailMessages;
private final List _mailboxListeners = Collections.synchronizedList(new ArrayList());
protected String name;
private Collection children;
@@ -39,14 +40,20 @@ class HierarchicalFolder implements MailFolder, UIDFolder {
private long nextUid = 1;
private long uidValidity;
- public HierarchicalFolder(HierarchicalFolder parent,
- String name) {
+ protected HierarchicalFolder(final StoredMessageCollectionFactory storedMessageCollectionFactory,
+ HierarchicalFolder parent, String name) {
+ this.storedMessageCollectionFactory = storedMessageCollectionFactory;
+ mailMessages = storedMessageCollectionFactory.createCollection();
this.name = name;
this.children = new ArrayList();
this.parent = parent;
this.uidValidity = System.currentTimeMillis();
}
+ public HierarchicalFolder(final HierarchicalFolder castParent, final String mailboxName) {
+ this(castParent.storedMessageCollectionFactory, castParent, mailboxName);
+ }
+
public Collection getChildren() {
return children;
}
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/store/InMemoryStore.java b/greenmail-core/src/main/java/com/icegreen/greenmail/store/InMemoryStore.java
index 5630f710a2..5b6bd0e4e9 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/store/InMemoryStore.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/store/InMemoryStore.java
@@ -21,10 +21,18 @@
*/
public class InMemoryStore
implements Store, ImapConstants {
+ private final RootFolder rootMailbox;
boolean quotaSupported = true;
- private RootFolder rootMailbox = new RootFolder();
private Map> quotaMap = new HashMap>();
+ public InMemoryStore() {
+ this(StoredMessageCollectionFactory.LIST_BASED_FACTORY);
+ }
+
+ public InMemoryStore(final StoredMessageCollectionFactory storedMessageCollectionFactory) {
+ this.rootMailbox = new RootFolder(storedMessageCollectionFactory);
+ }
+
@Override
public MailFolder getMailbox(String absoluteMailboxName) {
StringTokenizer tokens = new StringTokenizer(absoluteMailboxName, HIERARCHY_DELIMITER);
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/store/RootFolder.java b/greenmail-core/src/main/java/com/icegreen/greenmail/store/RootFolder.java
index 58360a4700..bc0af12701 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/store/RootFolder.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/store/RootFolder.java
@@ -10,8 +10,8 @@
* @author Raimund Klein
*/
class RootFolder extends HierarchicalFolder {
- public RootFolder() {
- super(null, ImapConstants.USER_NAMESPACE);
+ RootFolder(final StoredMessageCollectionFactory storedMessageCollectionFactory) {
+ super(storedMessageCollectionFactory, null, ImapConstants.USER_NAMESPACE);
}
@Override
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/store/StoredMessageCollectionFactory.java b/greenmail-core/src/main/java/com/icegreen/greenmail/store/StoredMessageCollectionFactory.java
new file mode 100644
index 0000000000..209681d5f8
--- /dev/null
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/store/StoredMessageCollectionFactory.java
@@ -0,0 +1,75 @@
+/* -------------------------------------------------------------------
+* This software is released under the Apache license 2.0
+* -------------------------------------------------------------------
+*/
+package com.icegreen.greenmail.store;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * @author Raimund Klein
+ */
+public enum StoredMessageCollectionFactory {
+ LIST_BASED_FACTORY {
+ @Override
+ StoredMessageCollection createCollection() {
+ return new ListBasedStoredMessageCollection();
+ }
+ },
+ MAP_BASED_FACTORY {
+ private static final int DEFAULT_MAXIMUM_MAP_SIZE = 5000;
+
+ @Override
+ protected Set getAcceptedConfigurationKeys() {
+ final Set acceptedKeys = super.getAcceptedConfigurationKeys();
+ acceptedKeys.add(Constants.CONFIGURATION_KEY_MAXIMUM_MAP_SIZE);
+ return acceptedKeys;
+ }
+
+ @Override
+ StoredMessageCollection createCollection() {
+ final int maximumMapSize = hasConfigurationFor(Constants.CONFIGURATION_KEY_MAXIMUM_MAP_SIZE) ?
+ (Integer) getConfiguredValue
+ (Constants.CONFIGURATION_KEY_MAXIMUM_MAP_SIZE) : DEFAULT_MAXIMUM_MAP_SIZE;
+ return new MapBasedStoredMessageCollection(maximumMapSize);
+ }
+ };
+
+ private final Map configuration;
+
+ StoredMessageCollectionFactory() {
+ configuration = new ConcurrentHashMap();
+ }
+
+ abstract StoredMessageCollection createCollection();
+
+ protected Set getAcceptedConfigurationKeys() {
+ return new HashSet();
+ }
+
+ protected final Object getConfiguredValue(final String configurationKey) {
+ return configuration.get(configurationKey);
+ }
+
+ protected final boolean hasConfigurationFor(final String configurationKey) {
+ return configuration.containsKey(configurationKey);
+ }
+
+ public final StoredMessageCollectionFactory withConfigurationValue(final String key, final Object value) {
+ final Set acceptedKeys = getAcceptedConfigurationKeys();
+ if (acceptedKeys.contains(key)) {
+ configuration.put(key, value);
+ return this;
+ }
+
+ throw new IllegalArgumentException(String.format("Configuration key '%s' unknown. Accepted keys are:%s", key,
+ acceptedKeys));
+ }
+
+ public static class Constants {
+ public static final String CONFIGURATION_KEY_MAXIMUM_MAP_SIZE = "CONFIGURATION_KEY_MAXIMUM_MAP_SIZE";
+ }
+}
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/user/UserImpl.java b/greenmail-core/src/main/java/com/icegreen/greenmail/user/UserImpl.java
index ec2d66602e..8c309baf9d 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/user/UserImpl.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/user/UserImpl.java
@@ -16,9 +16,9 @@
public class UserImpl implements GreenMailUser {
- String email;
private final int cachedHashCode;
private final String cachedHashCodeAsString;
+ String email;
String login;
String password;
private ImapHostManager imapHostManager;
@@ -46,9 +46,9 @@ public void delete() {
try {
imapHostManager.deleteMailbox(this, ImapConstants.INBOX_NAME);
} catch (FolderException e) {
- throw new IllegalStateException("Can not delete user "+this, e);
+ throw new IllegalStateException("Can not delete user " + this, e);
} catch (AuthorizationException e) {
- throw new IllegalStateException("Can not delete user "+this, e);
+ throw new IllegalStateException("Can not delete user " + this, e);
}
}
diff --git a/greenmail-core/src/main/java/com/icegreen/greenmail/util/GreenMail.java b/greenmail-core/src/main/java/com/icegreen/greenmail/util/GreenMail.java
index 1c5354f2c9..c901dc9980 100644
--- a/greenmail-core/src/main/java/com/icegreen/greenmail/util/GreenMail.java
+++ b/greenmail-core/src/main/java/com/icegreen/greenmail/util/GreenMail.java
@@ -58,12 +58,36 @@ public GreenMail(ServerSetup[] config) {
init();
}
+ /**
+ * Create the required services according to the server setup
+ *
+ * @param config Service configuration
+ * @return Services map
+ */
+ private static Map createServices(ServerSetup[] config, Managers mgr) {
+ Map srvc = new HashMap();
+ for (ServerSetup setup : config) {
+ if (srvc.containsKey(setup.getProtocol())) {
+ throw new IllegalArgumentException("Server '" + setup.getProtocol() + "' was found at least twice in the array");
+ }
+ final String protocol = setup.getProtocol();
+ if (protocol.startsWith(ServerSetup.PROTOCOL_SMTP)) {
+ srvc.put(protocol, new SmtpServer(setup, mgr));
+ } else if (protocol.startsWith(ServerSetup.PROTOCOL_POP3)) {
+ srvc.put(protocol, new Pop3Server(setup, mgr));
+ } else if (protocol.startsWith(ServerSetup.PROTOCOL_IMAP)) {
+ srvc.put(protocol, new ImapServer(setup, mgr));
+ }
+ }
+ return srvc;
+ }
+
/**
* Initialize
*/
private void init() {
if (managers == null) {
- managers = new Managers();
+ managers = createManagers();
}
if(services == null) {
services = createServices(config, managers);
@@ -118,7 +142,7 @@ public synchronized void stop() {
service.stopService();
}
}
- managers = new Managers();
+ managers.reset();
services = null;
}
@@ -128,30 +152,6 @@ public void reset() {
start();
}
- /**
- * Create the required services according to the server setup
- *
- * @param config Service configuration
- * @return Services map
- */
- private static Map createServices(ServerSetup[] config, Managers mgr) {
- Map srvc = new HashMap();
- for (ServerSetup setup : config) {
- if (srvc.containsKey(setup.getProtocol())) {
- throw new IllegalArgumentException("Server '" + setup.getProtocol() + "' was found at least twice in the array");
- }
- final String protocol = setup.getProtocol();
- if (protocol.startsWith(ServerSetup.PROTOCOL_SMTP)) {
- srvc.put(protocol, new SmtpServer(setup, mgr));
- } else if (protocol.startsWith(ServerSetup.PROTOCOL_POP3)) {
- srvc.put(protocol, new Pop3Server(setup, mgr));
- } else if (protocol.startsWith(ServerSetup.PROTOCOL_IMAP)) {
- srvc.put(protocol, new ImapServer(setup, mgr));
- }
- }
- return srvc;
- }
-
@Override
public SmtpServer getSmtp() {
return (SmtpServer) services.get(ServerSetup.PROTOCOL_SMTP);
diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/ManagersTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/ManagersTest.java
new file mode 100644
index 0000000000..32864ce59b
--- /dev/null
+++ b/greenmail-core/src/test/java/com/icegreen/greenmail/ManagersTest.java
@@ -0,0 +1,126 @@
+/*
+ * -------------------------------------------------------------------
+ * This software is released under the Apache license 2.0
+ * -------------------------------------------------------------------
+ * /
+ */
+
+package com.icegreen.greenmail;
+
+import com.icegreen.greenmail.imap.ImapHostManagerImpl;
+import com.icegreen.greenmail.smtp.SmtpManager;
+import com.icegreen.greenmail.store.InMemoryStore;
+import com.icegreen.greenmail.store.Store;
+import com.icegreen.greenmail.user.UserManager;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * @author Raimund Klein
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(Managers.class)
+public class ManagersTest {
+
+ @Test
+ public void shouldUseDefaultInMemoryStoreIfNoneGiven() throws Exception {
+ // Given
+ final InMemoryStore mockStore = createMockAndExpectNew(InMemoryStore.class);
+ replay(mockStore, InMemoryStore.class);
+
+ // When
+ new Managers();
+
+ // Then
+ verify(mockStore, InMemoryStore.class);
+ }
+
+ @Test
+ public void shouldCreateNewImapHostManagerImpl() throws Exception {
+ // Given
+ final Store store = new InMemoryStore();
+ final ImapHostManagerImpl mockHostManager = createMockAndExpectNew(ImapHostManagerImpl.class, store);
+ replay(mockHostManager, ImapHostManagerImpl.class);
+
+ // When
+ new Managers(store);
+
+ // Then
+ verify(mockHostManager, ImapHostManagerImpl.class);
+ }
+
+ @Test
+ public void shouldCreateNewUserManager() throws Exception {
+ // Given
+ final Store store = new InMemoryStore();
+ final ImapHostManagerImpl mockHostManager = createMock(ImapHostManagerImpl.class, store);
+ expectNew(ImapHostManagerImpl.class, store).andReturn(mockHostManager);
+ final UserManager mockUserManager = createMockAndExpectNew(UserManager.class, mockHostManager);
+ replay(mockHostManager, ImapHostManagerImpl.class, mockUserManager, UserManager.class);
+
+ // When
+ new Managers(store);
+
+ // Then
+ verify(mockUserManager, UserManager.class);
+ }
+
+ @Test
+ public void shouldCreateNewSmtpManager() throws Exception {
+ // Given
+ final Store store = new InMemoryStore();
+ final ImapHostManagerImpl mockHostManager = createMock(ImapHostManagerImpl.class, store);
+ expectNew(ImapHostManagerImpl.class, store).andReturn(mockHostManager);
+ final UserManager mockUserManager = createMock(UserManager.class, mockHostManager);
+ expectNew(UserManager.class, mockHostManager).andReturn(mockUserManager);
+ final SmtpManager mockSmtpManager = createMock(SmtpManager.class,
+ mockHostManager, mockUserManager);
+ replay(mockHostManager, ImapHostManagerImpl.class, mockUserManager, UserManager.class, mockSmtpManager,
+ SmtpManager.class);
+
+ // When
+ new Managers(store);
+
+ // Then
+ verify(mockSmtpManager, SmtpManager.class);
+ }
+
+ @Test
+ public void shouldCreateDefaultInMemoryStore() throws Exception {
+ // Given
+ final Managers managers = new Managers();
+ final Store mockStore = createMockAndExpectNew(InMemoryStore.class);
+ replay(mockStore, InMemoryStore.class);
+
+ // When
+ final Store createdStore = managers.createNewStore();
+
+ // Then
+ verify(mockStore, InMemoryStore.class);
+ assertThat(createdStore, is(mockStore));
+ }
+
+ @Test
+ public void shouldRecreateStoreAndAllSubManagers() throws Exception {
+ // Given
+ final Managers managers = new Managers();
+ final InMemoryStore mockStore = createMockAndExpectNew(InMemoryStore.class);
+ final ImapHostManagerImpl mockHostManager = createMockAndExpectNew(ImapHostManagerImpl.class, mockStore);
+ final UserManager mockUserManager = createMockAndExpectNew(UserManager.class, mockHostManager);
+ replay(mockStore, InMemoryStore.class, mockHostManager, ImapHostManagerImpl.class, mockUserManager,
+ UserManager.class);
+
+ // When
+ managers.reset();
+
+ // Then
+ verify(mockStore, InMemoryStore.class, mockHostManager, ImapHostManagerImpl.class, mockUserManager,
+ UserManager.class);
+ }
+}
\ No newline at end of file
diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/MemorySafeManagersTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/MemorySafeManagersTest.java
new file mode 100644
index 0000000000..0b36092154
--- /dev/null
+++ b/greenmail-core/src/test/java/com/icegreen/greenmail/MemorySafeManagersTest.java
@@ -0,0 +1,55 @@
+/*
+ * -------------------------------------------------------------------
+ * This software is released under the Apache license 2.0
+ * -------------------------------------------------------------------
+ * /
+ */
+
+package com.icegreen.greenmail;
+
+import com.icegreen.greenmail.store.InMemoryStore;
+import com.icegreen.greenmail.store.Store;
+import com.icegreen.greenmail.store.StoredMessageCollectionFactory;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * @author Raimund Klein
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(MemorySafeManagers.class)
+public class MemorySafeManagersTest {
+ @Test
+ public void shouldUseMapBasedFactoryInConstructor() throws Exception {
+ // Given
+ final InMemoryStore mockStore = createMockAndExpectNew(InMemoryStore.class, StoredMessageCollectionFactory.MAP_BASED_FACTORY);
+ replay(mockStore, InMemoryStore.class);
+
+ // When
+ new MemorySafeManagers();
+
+ // Then
+ verify(mockStore, InMemoryStore.class);
+ }
+
+ @Test
+ public void shouldCreateInMemoryStoreWithMapBasedFactory() throws Exception {
+ // Given
+ final Managers managers = new MemorySafeManagers();
+ final Store mockStore = createMockAndExpectNew(InMemoryStore.class, StoredMessageCollectionFactory.MAP_BASED_FACTORY);
+ replay(mockStore, InMemoryStore.class);
+
+ // When
+ final Store createdStore = managers.createNewStore();
+
+ // Then
+ verify(mockStore, InMemoryStore.class);
+ assertThat(createdStore, is(mockStore));
+ }
+}
\ No newline at end of file
diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/configuration/GreenMailConfigurationTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/configuration/GreenMailConfigurationTest.java
index 6452215a12..f4f7d61573 100644
--- a/greenmail-core/src/test/java/com/icegreen/greenmail/configuration/GreenMailConfigurationTest.java
+++ b/greenmail-core/src/test/java/com/icegreen/greenmail/configuration/GreenMailConfigurationTest.java
@@ -1,10 +1,14 @@
package com.icegreen.greenmail.configuration;
+import com.icegreen.greenmail.Managers;
+import com.icegreen.greenmail.MemorySafeManagers;
import com.icegreen.greenmail.util.GreenMail;
import com.icegreen.greenmail.util.ServerSetupTest;
import org.junit.Test;
+import static com.icegreen.greenmail.configuration.GreenMailConfigurationTestBase.testConfigWithMemorySafeManagers;
import static com.icegreen.greenmail.configuration.GreenMailConfigurationTestBase.testUsersAccessibleConfig;
+import static org.junit.Assert.assertSame;
/**
* Tests if the configuration is applied correctly to GreenMail instances.
@@ -23,4 +27,28 @@ public void testUsersAccessible() {
}
}
+ @Test
+ public void shouldCreateManagersClassByDefault() {
+ // Given
+ final GreenMail greenMail = new GreenMail(ServerSetupTest.IMAP);
+
+ // When
+ final Managers managers = greenMail.createManagers();
+
+ // Then
+ assertSame(Managers.class, managers.getClass());
+ }
+
+ @Test
+ public void shouldCreateMemorySafeManagersWhenConfigured() {
+ // Given
+ final GreenMail greenMail = new GreenMail(ServerSetupTest.IMAP).withConfiguration
+ (testConfigWithMemorySafeManagers());
+
+ // When
+ final Managers managers = greenMail.createManagers();
+
+ // Then
+ assertSame(MemorySafeManagers.class, managers.getClass());
+ }
}
\ No newline at end of file
diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/configuration/GreenMailConfigurationTestBase.java b/greenmail-core/src/test/java/com/icegreen/greenmail/configuration/GreenMailConfigurationTestBase.java
index a1788e7e82..04c2ddb74d 100644
--- a/greenmail-core/src/test/java/com/icegreen/greenmail/configuration/GreenMailConfigurationTestBase.java
+++ b/greenmail-core/src/test/java/com/icegreen/greenmail/configuration/GreenMailConfigurationTestBase.java
@@ -1,5 +1,6 @@
package com.icegreen.greenmail.configuration;
+import com.icegreen.greenmail.MemorySafeManagers;
import com.icegreen.greenmail.base.GreenMailOperations;
import com.icegreen.greenmail.util.Retriever;
@@ -45,4 +46,11 @@ public static GreenMailConfiguration testUsersAccessibleConfig() {
.withUser("user@localhost", "password")
.withUser("secondUser@localhost", "secondUserLogin", "password2");
}
+
+ /**
+ * @return A {@link GreenMailConfiguration} with {@link MemorySafeManagers} as Managers class.
+ */
+ public static GreenMailConfiguration testConfigWithMemorySafeManagers() {
+ return aConfig().withManagersClass(MemorySafeManagers.class);
+ }
}
diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/imap/ImapHostManagerImplTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/imap/ImapHostManagerImplTest.java
new file mode 100644
index 0000000000..f786c54c02
--- /dev/null
+++ b/greenmail-core/src/test/java/com/icegreen/greenmail/imap/ImapHostManagerImplTest.java
@@ -0,0 +1,34 @@
+/* -------------------------------------------------------------------
+* This software is released under the Apache license 2.0
+* -------------------------------------------------------------------
+*/
+package com.icegreen.greenmail.imap;
+
+import com.icegreen.greenmail.store.InMemoryStore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * @author Raimund Klein
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(ImapHostManagerImpl.class)
+public class ImapHostManagerImplTest {
+
+ @Test
+ public void shouldUseDefaultInMemoryStoreIfNoneGiven() throws Exception {
+ // Given
+ final InMemoryStore mockStore = createMockAndExpectNew(InMemoryStore.class);
+ replay(mockStore, InMemoryStore.class);
+
+ // When
+ new ImapHostManagerImpl();
+
+ // Then
+ verify(mockStore, InMemoryStore.class);
+ }
+}
\ No newline at end of file
diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/store/InMemoryStoreTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/store/InMemoryStoreTest.java
new file mode 100644
index 0000000000..7b0d3a12df
--- /dev/null
+++ b/greenmail-core/src/test/java/com/icegreen/greenmail/store/InMemoryStoreTest.java
@@ -0,0 +1,49 @@
+/* -------------------------------------------------------------------
+* This software is released under the Apache license 2.0
+* -------------------------------------------------------------------
+*/
+package com.icegreen.greenmail.store;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * @author Raimund Klein
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(InMemoryStore.class)
+public class InMemoryStoreTest {
+ @Test
+ public void shouldUsedListBasedFactoryByDefault() throws Exception {
+ // Given
+ final RootFolder mockFolder = createMockAndExpectNew(RootFolder.class, StoredMessageCollectionFactory
+ .LIST_BASED_FACTORY);
+ replay(mockFolder, RootFolder.class);
+
+ // When
+ new InMemoryStore();
+
+ // Then
+ verify(mockFolder, RootFolder.class);
+ }
+
+ @Test
+ public void shouldForwardGivenFactory() throws Exception {
+ for (final StoredMessageCollectionFactory factory : StoredMessageCollectionFactory.values()) {
+ // Given
+ final RootFolder mockFolder = createMockAndExpectNew(RootFolder.class, factory);
+ replay(mockFolder, RootFolder.class);
+
+ // When
+ new InMemoryStore(factory);
+
+ // Then
+ verify(mockFolder, RootFolder.class);
+ reset(RootFolder.class);
+ }
+ }
+}
\ No newline at end of file
diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/store/StoredMessageCollectionFactoryPowerMockTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/store/StoredMessageCollectionFactoryPowerMockTest.java
new file mode 100644
index 0000000000..50a40ab791
--- /dev/null
+++ b/greenmail-core/src/test/java/com/icegreen/greenmail/store/StoredMessageCollectionFactoryPowerMockTest.java
@@ -0,0 +1,66 @@
+/*
+ * -------------------------------------------------------------------
+ * This software is released under the Apache license 2.0
+ * -------------------------------------------------------------------
+ * /
+ */
+
+package com.icegreen.greenmail.store;
+
+import org.hamcrest.Matchers;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.powermock.api.easymock.PowerMock.*;
+
+/**
+ * @author Raimund Klein
+ */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(StoredMessageCollectionFactory.class)
+public class StoredMessageCollectionFactoryPowerMockTest {
+ // The following tests require a fix for PowerMock issue #552:
+ // https://code.google.com/p/powermock/issues/detail?id=552
+
+ @Test
+ @Ignore
+ public void shouldCreateMapBasedCollectionWithSize5000ByDefault() throws Exception {
+ // Given
+ final MapBasedStoredMessageCollection mockCollection = createMockAndExpectNew(MapBasedStoredMessageCollection
+ .class, new Class>[]{int.class}, 5000);
+ replay(mockCollection, MapBasedStoredMessageCollection.class);
+
+ // When
+ final StoredMessageCollection createdCollection = StoredMessageCollectionFactory.MAP_BASED_FACTORY
+ .createCollection();
+
+ // Then
+ assertThat(createdCollection, is(Matchers.sameInstance(mockCollection)));
+ verify(mockCollection, MapBasedStoredMessageCollection.class);
+ }
+
+ @Test
+ @Ignore
+ public void shouldCreateMapBasedCollectionWithGivenSizeIfPropertyIsSet() throws Exception {
+ // Given
+ final int expectedMapSize = 200;
+ StoredMessageCollectionFactory.MAP_BASED_FACTORY.withConfigurationValue(StoredMessageCollectionFactory
+ .Constants.CONFIGURATION_KEY_MAXIMUM_MAP_SIZE, expectedMapSize);
+ final MapBasedStoredMessageCollection mockCollection = createMockAndExpectNew(MapBasedStoredMessageCollection
+ .class, new Class>[]{int.class}, expectedMapSize);
+ replay(mockCollection, MapBasedStoredMessageCollection.class);
+
+ // When
+ final StoredMessageCollection createdCollection = StoredMessageCollectionFactory.MAP_BASED_FACTORY
+ .createCollection();
+
+ // Then
+ assertThat(createdCollection, is(Matchers.sameInstance(mockCollection)));
+ verify(mockCollection, MapBasedStoredMessageCollection.class);
+ }
+}
diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/store/StoredMessageCollectionFactoryTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/store/StoredMessageCollectionFactoryTest.java
new file mode 100644
index 0000000000..bef9bd198c
--- /dev/null
+++ b/greenmail-core/src/test/java/com/icegreen/greenmail/store/StoredMessageCollectionFactoryTest.java
@@ -0,0 +1,60 @@
+/* -------------------------------------------------------------------
+* This software is released under the Apache license 2.0
+* -------------------------------------------------------------------
+*/
+package com.icegreen.greenmail.store;
+
+import org.hamcrest.Matchers;
+import org.junit.Test;
+import org.junit.experimental.theories.DataPoints;
+import org.junit.experimental.theories.Theories;
+import org.junit.experimental.theories.Theory;
+import org.junit.runner.RunWith;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.fail;
+
+/**
+ * @author Raimund Klein
+ */
+@RunWith(Theories.class)
+public class StoredMessageCollectionFactoryTest {
+ @DataPoints
+ public static FactoryWithMatchingClass[] createFactoryPoints() {
+ return new FactoryWithMatchingClass[]{
+ new FactoryWithMatchingClass(StoredMessageCollectionFactory.LIST_BASED_FACTORY, ListBasedStoredMessageCollection.class),
+ new FactoryWithMatchingClass(StoredMessageCollectionFactory.MAP_BASED_FACTORY, MapBasedStoredMessageCollection.class)};
+ }
+
+ @Theory
+ public void shouldCreateMatchingCollection(final FactoryWithMatchingClass factoryWithMatchingClass) {
+ // When
+ final StoredMessageCollection collection = factoryWithMatchingClass.factory.createCollection();
+
+ // Then
+ assertThat(collection, is(Matchers.instanceOf(factoryWithMatchingClass.collectionClass)));
+ }
+
+ private static class FactoryWithMatchingClass {
+ private final StoredMessageCollectionFactory factory;
+ private final Class extends StoredMessageCollection> collectionClass;
+
+ private FactoryWithMatchingClass(StoredMessageCollectionFactory factory, Class extends StoredMessageCollection> collectionClass) {
+ this.factory = factory;
+ this.collectionClass = collectionClass;
+ }
+ }
+
+ @Test
+ public void shouldRejectUnknownProperty() {
+ for (final StoredMessageCollectionFactory factory : StoredMessageCollectionFactory.values()) {
+ try {
+ factory.withConfigurationValue("foo", "bar");
+ fail("Should have thrown exception");
+ } catch (IllegalArgumentException e) {
+ // This is expected.
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/test/GreenMailUtilTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/test/GreenMailUtilTest.java
index 42888c1086..e155f7f095 100644
--- a/greenmail-core/src/test/java/com/icegreen/greenmail/test/GreenMailUtilTest.java
+++ b/greenmail-core/src/test/java/com/icegreen/greenmail/test/GreenMailUtilTest.java
@@ -25,6 +25,26 @@
* @since Jan 29, 2006
*/
public class GreenMailUtilTest {
+ final static String SAMPLE_EMAIL = "From - Thu Jan 19 00:30:34 2006\r\n"
+ + "X-Account-Key: account245\r\n"
+ + "X-UIDL: 11332317636080.2607.mail5,S=833\r\n"
+ + "X-Mozilla-Status: 0001\r\n"
+ + "X-Mozilla-Status2: 00000000\r\n"
+ + "Return-Path: \r\n"
+ + "Delivered-To: eivar@blastigen.com\r\n"
+ + "Received: (qmail 2376 invoked from network); 19 Jan 2006 02:01:05 -0000\r\n"
+ + "Received: from unknown (HELO [192.168.0.5]) (hej@66.245.216.76)\r\n"
+ + "\tby mail5.hotmail.com with (RC4-MD5 encrypted) SMTP; Wed, 18 Jan 2006 18:01:05 -0800\r\n"
+ + "Message-ID: <43CEF322.7080702@hotmail.com>\r\n"
+ + "Date: Wed, 18 Jan 2006 18:02:10 -0800\r\n"
+ + "From: Wael Chatila \r\n"
+ + "User-Agent: Mozilla Thunderbird 1.0.7 (Windows/20050923)\r\n"
+ + "X-Accept-Language: en-us, en\r\n" + "MIME-Version: 1.0\r\n"
+ + "To: Bertil \r\n" + "Subject: wassup\r\n"
+ + "Content-Type: text/plain; charset=ISO-8859-1; format=flowed\r\n"
+ + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n"
+ + "Yo wassup Bertil\r\n";
+
@Test
public void testMimeMessageLoading() throws MessagingException {
MimeMessage message = GreenMailUtil.newMimeMessage(SAMPLE_EMAIL);
@@ -101,24 +121,4 @@ public void testSetAndGetQuota() throws MessagingException {
greenMail.stop();
}
}
-
- final static String SAMPLE_EMAIL = "From - Thu Jan 19 00:30:34 2006\r\n"
- + "X-Account-Key: account245\r\n"
- + "X-UIDL: 11332317636080.2607.mail5,S=833\r\n"
- + "X-Mozilla-Status: 0001\r\n"
- + "X-Mozilla-Status2: 00000000\r\n"
- + "Return-Path: \r\n"
- + "Delivered-To: eivar@blastigen.com\r\n"
- + "Received: (qmail 2376 invoked from network); 19 Jan 2006 02:01:05 -0000\r\n"
- + "Received: from unknown (HELO [192.168.0.5]) (hej@66.245.216.76)\r\n"
- + "\tby mail5.hotmail.com with (RC4-MD5 encrypted) SMTP; Wed, 18 Jan 2006 18:01:05 -0800\r\n"
- + "Message-ID: <43CEF322.7080702@hotmail.com>\r\n"
- + "Date: Wed, 18 Jan 2006 18:02:10 -0800\r\n"
- + "From: Wael Chatila \r\n"
- + "User-Agent: Mozilla Thunderbird 1.0.7 (Windows/20050923)\r\n"
- + "X-Accept-Language: en-us, en\r\n" + "MIME-Version: 1.0\r\n"
- + "To: Bertil \r\n" + "Subject: wassup\r\n"
- + "Content-Type: text/plain; charset=ISO-8859-1; format=flowed\r\n"
- + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n"
- + "Yo wassup Bertil\r\n";
}
diff --git a/greenmail-core/src/test/java/com/icegreen/greenmail/test/ServerStartStopTest.java b/greenmail-core/src/test/java/com/icegreen/greenmail/test/ServerStartStopTest.java
index ec02192e26..54c4e97dff 100644
--- a/greenmail-core/src/test/java/com/icegreen/greenmail/test/ServerStartStopTest.java
+++ b/greenmail-core/src/test/java/com/icegreen/greenmail/test/ServerStartStopTest.java
@@ -53,7 +53,7 @@ public void testServerStartupTimeout() {
}
// Set large startup timeout
- for(ServerSetup s: setups) {
+ for (ServerSetup s : setups) {
s.setServerStartupTimeout(3000L);
}
service = new GreenMail(setups);
diff --git a/greenmail-core/src/test/resources/log4j.xml b/greenmail-core/src/test/resources/log4j.xml
index 2d7728a79c..553a61dd01 100644
--- a/greenmail-core/src/test/resources/log4j.xml
+++ b/greenmail-core/src/test/resources/log4j.xml
@@ -26,7 +26,7 @@
-
+
diff --git a/greenmail-site/index.html b/greenmail-site/index.html
index 77a77d4c47..b2cfc7f26f 100644
--- a/greenmail-site/index.html
+++ b/greenmail-site/index.html
@@ -745,16 +745,18 @@ How can I use IMAP quotas?
ImapServerTest.java quota test
How can I create or delete a mail user?
+
-GreenMail greenMail = ...
-// Create user with login id equals email
-GreenMailUser user1 = greenMail.setUser("foo@localhost", "some secret pwd");
-// Create user with login id different than email
-GreenMailUser user2 = greenMail.setUser("foo@localhost", "login-id", "some secret pwd");
-...
-greenMail.getManagers().getUserManager().deleteUser(user1); // Delete user
-
+ GreenMail greenMail = ...
+ // Create user with login id equals email
+ GreenMailUser user1 = greenMail.setUser("foo@localhost", "some secret pwd");
+ // Create user with login id different than email
+ GreenMailUser user2 = greenMail.setUser("foo@localhost", "login-id", "some secret pwd");
+ ...
+ greenMail.getManagers().getUserManager().deleteUser(user1); // Delete user
+
+
diff --git a/pom.xml b/pom.xml
index c613cef6ca..6a1ae80b02 100644
--- a/pom.xml
+++ b/pom.xml
@@ -253,6 +253,7 @@
1.7.12
1.3
+ 1.6.3
4.1.7.RELEASE
UTF-8
UTF-8
@@ -365,6 +366,18 @@
3.2
test
+
+ org.powermock
+ powermock-module-junit4
+ ${powermock.version}
+ test
+
+
+ org.powermock
+ powermock-api-easymock
+ ${powermock.version}
+ test
+
org.hamcrest
hamcrest-core