Author: norman Date: Tue Apr 27 19:43:40 2010 New Revision: 938618 URL: http://svn.apache.org/viewvc?rev=938618&view=rev Log: Don't cache Mailboxes so we don't get problems with GC (IMAP-131). Not all tests passing yet, so work in progress
Added: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java james/imap/trunk/store/src/main/java/org/apache/james/imap/store/DelegatingMailboxListener.java Removed: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAUtils.java Modified: james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/inmemory/InMemoryHostSystem.java james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRGlobalUserMailboxManager.java james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPASubscriptionManager.java james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/openjpa/OpenJPAMailboxMapper.java james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java Modified: james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/inmemory/InMemoryHostSystem.java URL: http://svn.apache.org/viewvc/james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/inmemory/InMemoryHostSystem.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/inmemory/InMemoryHostSystem.java (original) +++ james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/inmemory/InMemoryHostSystem.java Tue Apr 27 19:43:40 2010 @@ -31,7 +31,7 @@ import org.apache.james.test.functional. public class InMemoryHostSystem extends ImapHostSystem { - private final StoreMailboxManager mailboxManager; + private final InMemoryMailboxManager mailboxManager; private final InMemoryUserManager userManager; static HostSystem build() throws Exception { @@ -57,7 +57,7 @@ public class InMemoryHostSystem extends @Override protected void resetData() throws Exception { - //mailboxManager.deleteEverything(); + mailboxManager.deleteEverything(); } } Modified: james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java URL: http://svn.apache.org/viewvc/james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java (original) +++ james/imap/trunk/deployment/src/test/java/org/apache/james/imap/functional/jpa/JPAHostSystem.java Tue Apr 27 19:43:40 2010 @@ -30,6 +30,7 @@ import org.apache.james.imap.encode.main import org.apache.james.imap.functional.ImapHostSystem; import org.apache.james.imap.functional.InMemoryUserManager; import org.apache.james.imap.jpa.JPASubscriptionManager; +import org.apache.james.imap.jpa.MailboxSessionEntityManagerFactory; import org.apache.james.imap.jpa.openjpa.OpenJPAMailboxManager; import org.apache.james.imap.mailbox.MailboxSession; import org.apache.james.imap.main.DefaultImapDecoderFactory; @@ -68,7 +69,8 @@ public class JPAHostSystem extends ImapH userManager = new InMemoryUserManager(); entityManagerFactory = OpenJPAPersistence.getEntityManagerFactory(properties); - mailboxManager = new OpenJPAMailboxManager(userManager, new JPASubscriptionManager(entityManagerFactory), entityManagerFactory); + MailboxSessionEntityManagerFactory factory = new MailboxSessionEntityManagerFactory(entityManagerFactory); + mailboxManager = new OpenJPAMailboxManager(userManager, new JPASubscriptionManager(factory), factory); final DefaultImapProcessorFactory defaultImapProcessorFactory = new DefaultImapProcessorFactory(); resetUserMetaData(); Modified: james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRGlobalUserMailboxManager.java URL: http://svn.apache.org/viewvc/james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRGlobalUserMailboxManager.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRGlobalUserMailboxManager.java (original) +++ james/imap/trunk/jcr/src/main/java/org/apache/james/imap/jcr/JCRGlobalUserMailboxManager.java Tue Apr 27 19:43:40 2010 @@ -71,7 +71,6 @@ public class JCRGlobalUserMailboxManager public void run() throws MailboxException { mapper.deleteAll(); - mailboxes.clear(); } }); Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java (original) +++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailbox.java Tue Apr 27 19:43:40 2010 @@ -25,7 +25,6 @@ import java.util.List; import javax.mail.Flags; import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; import org.apache.james.imap.jpa.mail.JPAMailboxMapper; import org.apache.james.imap.jpa.mail.JPAMessageMapper; @@ -50,9 +49,9 @@ import org.apache.james.imap.store.mail. */ public abstract class JPAMailbox extends StoreMailbox<Long> { - protected final EntityManagerFactory entityManagerFactory; + protected final MailboxSessionEntityManagerFactory entityManagerFactory; - public JPAMailbox(final MailboxEventDispatcher dispatcher, final Mailbox<Long> mailbox, final EntityManagerFactory entityManagerfactory) { + public JPAMailbox(final MailboxEventDispatcher dispatcher, final Mailbox<Long> mailbox, final MailboxSessionEntityManagerFactory entityManagerfactory) { super(dispatcher, mailbox); this.entityManagerFactory = entityManagerfactory; } @@ -73,10 +72,8 @@ public abstract class JPAMailbox extends @Override protected MessageMapper<Long> createMessageMapper(MailboxSession session) { - EntityManager manager = entityManagerFactory.createEntityManager(); - - JPAUtils.addEntityManager(session, manager); - + EntityManager manager = entityManagerFactory.getEntityManager(session); + JPAMessageMapper mapper = new JPAMessageMapper(manager, getMailboxId()); return mapper; @@ -111,7 +108,7 @@ public abstract class JPAMailbox extends * Reserve next Uid in mailbox and return the mailbox. This method needs to be synchronized * to be sure we don't get any race-condition */ - protected synchronized Mailbox<Long> reserveNextUid(MailboxSession session) throws MailboxException { + protected Mailbox<Long> reserveNextUid(MailboxSession session) throws MailboxException { final JPAMailboxMapper mapper = createMailboxMapper(session); final Mailbox<Long> mailbox = mapper.consumeNextUid(getMailboxId()); return mailbox; Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java (original) +++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPAMailboxManager.java Tue Apr 27 19:43:40 2010 @@ -18,10 +18,6 @@ ****************************************************************/ package org.apache.james.imap.jpa; -import java.util.List; - -import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; import org.apache.james.imap.mailbox.MailboxException; import org.apache.james.imap.mailbox.MailboxSession; @@ -40,10 +36,10 @@ import org.apache.james.imap.store.trans */ public abstract class JPAMailboxManager extends StoreMailboxManager<Long> { - protected final EntityManagerFactory entityManagerFactory; + protected final MailboxSessionEntityManagerFactory entityManagerFactory; public JPAMailboxManager(final Authenticator authenticator, final Subscriber subscriber, - final EntityManagerFactory entityManagerFactory) { + final MailboxSessionEntityManagerFactory entityManagerFactory) { super(authenticator, subscriber); this.entityManagerFactory = entityManagerFactory; } @@ -68,25 +64,17 @@ public abstract class JPAMailboxManager public void run() throws MailboxException { mapper.deleteAll(); - mailboxes.clear(); } }); } + @Override public void endProcessingRequest(MailboxSession session) { - List<EntityManager> managers = JPAUtils.getEntityManagers(session); - for (int i = 0 ; i < managers.size(); i++) { - EntityManager manager = managers.get(i); - if (manager.isOpen()) { - try { - manager.close(); - } catch (Exception e) { - // just catch exceptions on logout - } - } - } + // close the entityManager after each request so we are sure everything is flushed + entityManagerFactory.closeEntityManager(session); + } Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPASubscriptionManager.java URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPASubscriptionManager.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPASubscriptionManager.java (original) +++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/JPASubscriptionManager.java Tue Apr 27 19:43:40 2010 @@ -19,7 +19,6 @@ package org.apache.james.imap.jpa; import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; import org.apache.james.imap.jpa.user.JPASubscriptionMapper; import org.apache.james.imap.jpa.user.model.JPASubscription; @@ -34,9 +33,9 @@ import org.apache.james.imap.store.user. * */ public class JPASubscriptionManager extends StoreSubscriptionManager { - private final EntityManagerFactory factory; + private final MailboxSessionEntityManagerFactory factory; - public JPASubscriptionManager(final EntityManagerFactory factory) { + public JPASubscriptionManager(final MailboxSessionEntityManagerFactory factory) { super(); this.factory = factory; } @@ -46,10 +45,8 @@ public class JPASubscriptionManager exte * @see org.apache.james.imap.store.StoreSubscriptionManager#createMapper(org.apache.james.imap.mailbox.MailboxSession) */ protected SubscriptionMapper createMapper(MailboxSession session) { - EntityManager manager = factory.createEntityManager(); - - JPAUtils.addEntityManager(session, manager); - + EntityManager manager = factory.getEntityManager(session); + JPASubscriptionMapper mapper = new JPASubscriptionMapper(manager); return mapper; Added: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java?rev=938618&view=auto ============================================================================== --- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java (added) +++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/MailboxSessionEntityManagerFactory.java Tue Apr 27 19:43:40 2010 @@ -0,0 +1,35 @@ +package org.apache.james.imap.jpa; + +import javax.persistence.EntityManager; +import javax.persistence.EntityManagerFactory; + +import org.apache.james.imap.mailbox.MailboxSession; + +public class MailboxSessionEntityManagerFactory { + + private EntityManagerFactory factory; + private final static String ENTITYMANAGER = "ENTITYMANAGER"; + + public MailboxSessionEntityManagerFactory(EntityManagerFactory factory) { + this.factory = factory; + } + + public EntityManager getEntityManager(MailboxSession session) { + EntityManager manager = (EntityManager) session.getAttributes().get(ENTITYMANAGER); + if (manager == null || manager.isOpen() == false) { + manager = factory.createEntityManager(); + session.getAttributes().put(ENTITYMANAGER, manager); + } + + return manager; + } + + public void closeEntityManager(MailboxSession session) { + if (session != null) { + EntityManager manager = (EntityManager) session.getAttributes().remove(ENTITYMANAGER); + if ( manager != null && manager.isOpen()) { + manager.close(); + } + } + } +} Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java (original) +++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/JPAMailboxMapper.java Tue Apr 27 19:43:40 2010 @@ -150,6 +150,7 @@ public abstract class JPAMailboxMapper e } catch (NoResultException e) { throw new MailboxNotFoundException(mailboxId); } catch (PersistenceException e) { + e.printStackTrace(); throw new StorageException(HumanReadableText.COMSUME_UID_FAILED, e); } } Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/openjpa/OpenJPAMailboxMapper.java URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/openjpa/OpenJPAMailboxMapper.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/openjpa/OpenJPAMailboxMapper.java (original) +++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/mail/openjpa/OpenJPAMailboxMapper.java Tue Apr 27 19:43:40 2010 @@ -23,11 +23,9 @@ import javax.persistence.EntityManager; import org.apache.james.imap.jpa.mail.JPAMailboxMapper; import org.apache.james.imap.jpa.mail.model.JPAMailbox; -import org.apache.openjpa.persistence.OpenJPAEntityManager; -import org.apache.openjpa.persistence.OpenJPAPersistence; /** - * OpenJPA implemetnation of MailboxMapper. + * OpenJPA implementation of MailboxMapper. */ public class OpenJPAMailboxMapper extends JPAMailboxMapper { @@ -40,18 +38,10 @@ public class OpenJPAMailboxMapper extend * @see org.apache.james.imap.jpa.mail.JPAMailboxMapper#doConsumeNextUid(long) */ public JPAMailbox doConsumeNextUid(long mailboxId) { - OpenJPAEntityManager oem = OpenJPAPersistence.cast(entityManager); - final boolean originalLocking = oem.getOptimistic(); - oem.setOptimistic(false); - oem.getTransaction().begin(); - try { - JPAMailbox mailbox = (JPAMailbox) entityManager.createNamedQuery("findMailboxById").setParameter("idParam", mailboxId).getSingleResult(); - mailbox.consumeUid(); - oem.persist(mailbox); - oem.getTransaction().commit(); - return mailbox; - } finally { - oem.setOptimistic(originalLocking); - } + JPAMailbox mailbox = (JPAMailbox) entityManager.createNamedQuery("findMailboxById").setParameter("idParam", mailboxId).getSingleResult(); + mailbox.consumeUid(); + entityManager.persist(mailbox); + return mailbox; + } } Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java (original) +++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailbox.java Tue Apr 27 19:43:40 2010 @@ -26,10 +26,9 @@ import java.util.List; import javax.mail.Flags; import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; import org.apache.james.imap.jpa.JPAMailbox; -import org.apache.james.imap.jpa.JPAUtils; +import org.apache.james.imap.jpa.MailboxSessionEntityManagerFactory; import org.apache.james.imap.jpa.mail.JPAMailboxMapper; import org.apache.james.imap.jpa.mail.model.AbstractJPAMailboxMembership; import org.apache.james.imap.jpa.mail.model.JPAHeader; @@ -49,13 +48,12 @@ import org.apache.james.imap.store.mail. */ public class OpenJPAMailbox extends JPAMailbox{ - public final static String MAILBOX_MAPPER = "MAILBOX_MAPPER"; private final boolean useStreaming; - public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> mailbox, EntityManagerFactory entityManagerfactory) { + public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> mailbox, MailboxSessionEntityManagerFactory entityManagerfactory) { this(dispatcher, mailbox, entityManagerfactory, false); } - public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> mailbox, EntityManagerFactory entityManagerfactory, final boolean useStreaming) { + public OpenJPAMailbox(MailboxEventDispatcher dispatcher, Mailbox<Long> mailbox, MailboxSessionEntityManagerFactory entityManagerfactory, final boolean useStreaming) { super(dispatcher, mailbox, entityManagerfactory); this.useStreaming = useStreaming; } @@ -65,10 +63,8 @@ public class OpenJPAMailbox extends JPAM * @see org.apache.james.imap.jpa.JPAMailbox#createMailboxMapper(org.apache.james.imap.mailbox.MailboxSession) */ protected JPAMailboxMapper createMailboxMapper(MailboxSession session) { - EntityManager manager = entityManagerFactory.createEntityManager(); - - JPAUtils.addEntityManager(session, manager); - + EntityManager manager = entityManagerFactory.getEntityManager(session); + JPAMailboxMapper mapper = new OpenJPAMailboxMapper(manager); return mapper; Modified: james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java URL: http://svn.apache.org/viewvc/james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java (original) +++ james/imap/trunk/jpa/src/main/java/org/apache/james/imap/jpa/openjpa/OpenJPAMailboxManager.java Tue Apr 27 19:43:40 2010 @@ -20,10 +20,9 @@ package org.apache.james.imap.jpa.openjpa; import javax.persistence.EntityManager; -import javax.persistence.EntityManagerFactory; import org.apache.james.imap.jpa.JPAMailboxManager; -import org.apache.james.imap.jpa.JPAUtils; +import org.apache.james.imap.jpa.MailboxSessionEntityManagerFactory; import org.apache.james.imap.jpa.mail.openjpa.OpenJPAMailboxMapper; import org.apache.james.imap.mailbox.MailboxSession; import org.apache.james.imap.mailbox.util.MailboxEventDispatcher; @@ -41,19 +40,18 @@ public class OpenJPAMailboxManager exten private boolean useStreaming; - public OpenJPAMailboxManager(Authenticator authenticator, Subscriber subscriber, EntityManagerFactory entityManagerFactory, boolean useStreaming) { + public OpenJPAMailboxManager(Authenticator authenticator, Subscriber subscriber, MailboxSessionEntityManagerFactory entityManagerFactory, boolean useStreaming) { super(authenticator, subscriber, entityManagerFactory); this.useStreaming = useStreaming; } - public OpenJPAMailboxManager(Authenticator authenticator, Subscriber subscriber, EntityManagerFactory entityManagerFactory) { + public OpenJPAMailboxManager(Authenticator authenticator, Subscriber subscriber, MailboxSessionEntityManagerFactory entityManagerFactory) { this(authenticator, subscriber, entityManagerFactory, false); } @Override protected MailboxMapper<Long> createMailboxMapper(MailboxSession session) { - EntityManager manager = entityManagerFactory.createEntityManager(); - JPAUtils.addEntityManager(session, manager); + EntityManager manager = entityManagerFactory.getEntityManager(session); return new OpenJPAMailboxMapper(manager); } Modified: james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java URL: http://svn.apache.org/viewvc/james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java (original) +++ james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryMailboxManager.java Tue Apr 27 19:43:40 2010 @@ -69,7 +69,7 @@ public class InMemoryMailboxManager exte * (non-Javadoc) * @see org.apache.james.imap.store.mail.MailboxMapper#countMailboxesWithName(java.lang.String) */ - public long countMailboxesWithName(String name) throws StorageException { + public synchronized long countMailboxesWithName(String name) throws StorageException { int total = 0; for (final InMemoryMailbox mailbox:mailboxesById.values()) { if (mailbox.getName().equals(name)) { @@ -83,7 +83,7 @@ public class InMemoryMailboxManager exte * (non-Javadoc) * @see org.apache.james.imap.store.mail.MailboxMapper#delete(org.apache.james.imap.store.mail.model.Mailbox) */ - public void delete(Mailbox<Long> mailbox) throws StorageException { + public synchronized void delete(Mailbox<Long> mailbox) throws StorageException { mailboxesById.remove(mailbox.getMailboxId()); } @@ -91,7 +91,7 @@ public class InMemoryMailboxManager exte * (non-Javadoc) * @see org.apache.james.imap.store.mail.MailboxMapper#deleteAll() */ - public void deleteAll() throws StorageException { + public synchronized void deleteAll() throws StorageException { mailboxesById.clear(); } @@ -100,7 +100,7 @@ public class InMemoryMailboxManager exte * (non-Javadoc) * @see org.apache.james.imap.store.mail.MailboxMapper#findMailboxById(java.lang.Object) */ - public Mailbox<Long> findMailboxById(Long mailboxId) throws StorageException, MailboxNotFoundException { + public synchronized Mailbox<Long> findMailboxById(Long mailboxId) throws StorageException, MailboxNotFoundException { return mailboxesById.get(mailboxesById); } @@ -108,7 +108,7 @@ public class InMemoryMailboxManager exte * (non-Javadoc) * @see org.apache.james.imap.store.mail.MailboxMapper#findMailboxByName(java.lang.String) */ - public Mailbox<Long> findMailboxByName(String name) throws StorageException, MailboxNotFoundException { + public synchronized Mailbox<Long> findMailboxByName(String name) throws StorageException, MailboxNotFoundException { Mailbox<Long> result = null; for (final InMemoryMailbox mailbox:mailboxesById.values()) { if (mailbox.getName().equals(name)) { @@ -123,7 +123,7 @@ public class InMemoryMailboxManager exte * (non-Javadoc) * @see org.apache.james.imap.store.mail.MailboxMapper#findMailboxWithNameLike(java.lang.String) */ - public List<Mailbox<Long>> findMailboxWithNameLike(String name) throws StorageException { + public synchronized List<Mailbox<Long>> findMailboxWithNameLike(String name) throws StorageException { final String regex = name.replace("%", ".*"); List<Mailbox<Long>> results = new ArrayList<Mailbox<Long>>(); for (final InMemoryMailbox mailbox:mailboxesById.values()) { @@ -138,7 +138,7 @@ public class InMemoryMailboxManager exte * (non-Javadoc) * @see org.apache.james.imap.store.mail.MailboxMapper#existsMailboxStartingWith(java.lang.String) */ - public boolean existsMailboxStartingWith(String mailboxName) throws StorageException { + public synchronized boolean existsMailboxStartingWith(String mailboxName) throws StorageException { boolean result = false; for (final InMemoryMailbox mailbox:mailboxesById.values()) { if (mailbox.getName().startsWith(mailboxName)) { @@ -153,7 +153,7 @@ public class InMemoryMailboxManager exte * (non-Javadoc) * @see org.apache.james.imap.store.mail.MailboxMapper#save(org.apache.james.imap.store.mail.model.Mailbox) */ - public void save(Mailbox<Long> mailbox) throws StorageException { + public synchronized void save(Mailbox<Long> mailbox) throws StorageException { mailboxesById.put(mailbox.getMailboxId(), (InMemoryMailbox) mailbox); } @@ -171,13 +171,12 @@ public class InMemoryMailboxManager exte * @throws MailboxException */ - public void deleteEverything() throws MailboxException { + public synchronized void deleteEverything() throws MailboxException { final MailboxMapper<Long> mapper = createMailboxMapper(null); mapper.execute(new TransactionalMapper.Transaction() { public void run() throws MailboxException { mapper.deleteAll(); - mailboxes.clear(); } }); Modified: james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java URL: http://svn.apache.org/viewvc/james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java (original) +++ james/imap/trunk/memory/src/main/java/org/apache/james/imap/inmemory/InMemoryStoreMailbox.java Tue Apr 27 19:43:40 2010 @@ -56,6 +56,7 @@ public class InMemoryStoreMailbox extend this.mailbox = mailbox; this.membershipByUid = new ConcurrentHashMap<Long, MailboxMembership<Long>>(INITIAL_SIZE); } + @Override protected MailboxMembership<Long> copyMessage(MailboxMembership<Long> originalMessage, long uid, MailboxSession session) { Added: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/DelegatingMailboxListener.java URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/DelegatingMailboxListener.java?rev=938618&view=auto ============================================================================== --- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/DelegatingMailboxListener.java (added) +++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/DelegatingMailboxListener.java Tue Apr 27 19:43:40 2010 @@ -0,0 +1,74 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.james.imap.store; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.james.imap.mailbox.MailboxListener; + +/** + * Receive a {...@link Event} and delegate it to an other {...@link MailboxListener} depending on the registered name + * + */ +public class DelegatingMailboxListener implements MailboxListener{ + + private Map<String,List<MailboxListener>> listeners = new HashMap<String, List<MailboxListener>>(); + + public synchronized void addListener(String name, MailboxListener listener) { + List<MailboxListener> mListeners = listeners.get(name); + if (mListeners == null) { + mListeners = new ArrayList<MailboxListener>(); + listeners.put(name, mListeners); + } + if (mListeners.contains(listener) == false) { + mListeners.add(listener); + } + } + + + /* + * (non-Javadoc) + * @see org.apache.james.imap.mailbox.MailboxListener#event(org.apache.james.imap.mailbox.MailboxListener.Event) + */ + public synchronized void event(Event event) { + List<MailboxListener> mListeners = listeners.get(event.getMailboxName()); + if (mListeners != null && mListeners.isEmpty() == false) { + for (int i = 0; i < mListeners.size(); i++) { + MailboxListener l = mListeners.get(i); + if (l.isClosed()) { + mListeners.remove(l); + } else { + l.event(event); + } + } + } + } + + /** + * Is never closed + */ + public boolean isClosed() { + return false; + } + +} Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java (original) +++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailbox.java Tue Apr 27 19:43:40 2010 @@ -145,166 +145,165 @@ public abstract class StoreMailbox<Id> i * (non-Javadoc) * @see org.apache.james.imap.mailbox.Mailbox#appendMessage(byte[], java.util.Date, org.apache.james.imap.mailbox.MailboxSession, boolean, javax.mail.Flags) */ - public long appendMessage(InputStream msgIn, Date internalDate, - MailboxSession mailboxSession, boolean isRecent, Flags flagsToBeSet) + public long appendMessage(final InputStream msgIn, final Date internalDate, + final MailboxSession mailboxSession,final boolean isRecent, final Flags flagsToBeSet) throws MailboxException { - - final Mailbox<Id> mailbox = reserveNextUid(mailboxSession); - if (mailbox == null) { - throw new MailboxNotFoundException("Mailbox has been deleted"); - } else { - - - File file = null; - try { - // Create a temporary file and copy the message to it. We will work with the file as - // source for the InputStream - file = File.createTempFile("imap", ".msg"); - FileOutputStream out = new FileOutputStream(file); - - byte[] buf = new byte[1024]; - int i = 0; - while ((i = msgIn.read(buf)) != -1) { - out.write(buf, 0, i); - } - out.flush(); - out.close(); - - FileInputStream tmpMsgIn = new FileInputStream(file); - // To be thread safe, we first get our own copy and the - // exclusive - // Uid - // TODO create own message_id and assign uid later - // at the moment it could lead to the situation that uid 5 - // is - // inserted long before 4, when - // mail 4 is big and comes over a slow connection. - - final long uid = mailbox.getLastUid(); - final int size = tmpMsgIn.available(); - final int bodyStartOctet = bodyStartOctet(new FileInputStream(file)); - - // Disable line length... This should be handled by the smtp server component and not the parser itself - // https://issues.apache.org/jira/browse/IMAP-122 - MimeEntityConfig config = new MimeEntityConfig(); - config.setMaximalBodyDescriptor(true); - config.setMaxLineLen(-1); - final ConfigurableMimeTokenStream parser = new ConfigurableMimeTokenStream(config); - - parser.setRecursionMode(MimeTokenStream.M_NO_RECURSE); - parser.parse(new FileInputStream(file)); - final List<Header> headers = new ArrayList<Header>(INITIAL_SIZE_HEADERS); + // this will hold the uid after the transaction was complete + final List<Long> uidHolder = new ArrayList<Long>(); + final MessageMapper<Id> mapper = createMessageMapper(mailboxSession); + mapper.execute(new TransactionalMapper.Transaction() { + + public void run() throws MailboxException { + final Mailbox<Id> mailbox = reserveNextUid(mailboxSession); - int lineNumber = 0; - int next = parser.next(); - while (next != MimeTokenStream.T_BODY - && next != MimeTokenStream.T_END_OF_STREAM - && next != MimeTokenStream.T_START_MULTIPART) { - if (next == MimeTokenStream.T_FIELD) { - String fieldValue = parser.getField().getBody(); - if (fieldValue.endsWith("\r\f")) { - fieldValue = fieldValue.substring(0,fieldValue.length() - 2); + File file = null; + try { + // Create a temporary file and copy the message to it. We will work with the file as + // source for the InputStream + file = File.createTempFile("imap", ".msg"); + FileOutputStream out = new FileOutputStream(file); + + byte[] buf = new byte[1024]; + int i = 0; + while ((i = msgIn.read(buf)) != -1) { + out.write(buf, 0, i); + } + out.flush(); + out.close(); + + FileInputStream tmpMsgIn = new FileInputStream(file); + // To be thread safe, we first get our own copy and the + // exclusive + // Uid + // TODO create own message_id and assign uid later + // at the moment it could lead to the situation that uid 5 + // is + // inserted long before 4, when + // mail 4 is big and comes over a slow connection. + + final long uid = mailbox.getLastUid(); + final int size = tmpMsgIn.available(); + final int bodyStartOctet = bodyStartOctet(new FileInputStream(file)); + + // Disable line length... This should be handled by the smtp server component and not the parser itself + // https://issues.apache.org/jira/browse/IMAP-122 + MimeEntityConfig config = new MimeEntityConfig(); + config.setMaximalBodyDescriptor(true); + config.setMaxLineLen(-1); + final ConfigurableMimeTokenStream parser = new ConfigurableMimeTokenStream(config); + + parser.setRecursionMode(MimeTokenStream.M_NO_RECURSE); + parser.parse(new FileInputStream(file)); + final List<Header> headers = new ArrayList<Header>(INITIAL_SIZE_HEADERS); + + int lineNumber = 0; + int next = parser.next(); + while (next != MimeTokenStream.T_BODY + && next != MimeTokenStream.T_END_OF_STREAM + && next != MimeTokenStream.T_START_MULTIPART) { + if (next == MimeTokenStream.T_FIELD) { + String fieldValue = parser.getField().getBody(); + if (fieldValue.endsWith("\r\f")) { + fieldValue = fieldValue.substring(0,fieldValue.length() - 2); + } + if (fieldValue.startsWith(" ")) { + fieldValue = fieldValue.substring(1); + } + final Header header + = createHeader(++lineNumber, parser.getField().getName(), + fieldValue); + headers.add(header); } - if (fieldValue.startsWith(" ")) { - fieldValue = fieldValue.substring(1); + next = parser.next(); + } + final MaximalBodyDescriptor descriptor = (MaximalBodyDescriptor) parser.getBodyDescriptor(); + final PropertyBuilder propertyBuilder = new PropertyBuilder(); + final String mediaType; + final String mediaTypeFromHeader = descriptor.getMediaType(); + final String subType; + if (mediaTypeFromHeader == null) { + mediaType = "text"; + subType = "plain"; + } else { + mediaType = mediaTypeFromHeader; + subType = descriptor.getSubType(); + } + propertyBuilder.setMediaType(mediaType); + propertyBuilder.setSubType(subType); + propertyBuilder.setContentID(descriptor.getContentId()); + propertyBuilder.setContentDescription(descriptor.getContentDescription()); + propertyBuilder.setContentLocation(descriptor.getContentLocation()); + propertyBuilder.setContentMD5(descriptor.getContentMD5Raw()); + propertyBuilder.setContentTransferEncoding(descriptor.getTransferEncoding()); + propertyBuilder.setContentLanguage(descriptor.getContentLanguage()); + propertyBuilder.setContentDispositionType(descriptor.getContentDispositionType()); + propertyBuilder.setContentDispositionParameters(descriptor.getContentDispositionParameters()); + propertyBuilder.setContentTypeParameters(descriptor.getContentTypeParameters()); + // Add missing types + final String codeset = descriptor.getCharset(); + if (codeset == null) { + if ("TEXT".equalsIgnoreCase(mediaType)) { + propertyBuilder.setCharset("us-ascii"); } - final Header header - = createHeader(++lineNumber, parser.getField().getName(), - fieldValue); - headers.add(header); + } else { + propertyBuilder.setCharset(codeset); } - next = parser.next(); - } - final MaximalBodyDescriptor descriptor = (MaximalBodyDescriptor) parser.getBodyDescriptor(); - final PropertyBuilder propertyBuilder = new PropertyBuilder(); - final String mediaType; - final String mediaTypeFromHeader = descriptor.getMediaType(); - final String subType; - if (mediaTypeFromHeader == null) { - mediaType = "text"; - subType = "plain"; - } else { - mediaType = mediaTypeFromHeader; - subType = descriptor.getSubType(); - } - propertyBuilder.setMediaType(mediaType); - propertyBuilder.setSubType(subType); - propertyBuilder.setContentID(descriptor.getContentId()); - propertyBuilder.setContentDescription(descriptor.getContentDescription()); - propertyBuilder.setContentLocation(descriptor.getContentLocation()); - propertyBuilder.setContentMD5(descriptor.getContentMD5Raw()); - propertyBuilder.setContentTransferEncoding(descriptor.getTransferEncoding()); - propertyBuilder.setContentLanguage(descriptor.getContentLanguage()); - propertyBuilder.setContentDispositionType(descriptor.getContentDispositionType()); - propertyBuilder.setContentDispositionParameters(descriptor.getContentDispositionParameters()); - propertyBuilder.setContentTypeParameters(descriptor.getContentTypeParameters()); - // Add missing types - final String codeset = descriptor.getCharset(); - if (codeset == null) { - if ("TEXT".equalsIgnoreCase(mediaType)) { - propertyBuilder.setCharset("us-ascii"); + + final String boundary = descriptor.getBoundary(); + if (boundary != null) { + propertyBuilder.setBoundary(boundary); + } + if ("text".equalsIgnoreCase(mediaType)) { + final CountingInputStream bodyStream = new CountingInputStream(parser.getInputStream()); + bodyStream.readAll(); + long lines = bodyStream.getLineCount(); + + next = parser.next(); + if (next == MimeTokenStream.T_EPILOGUE) { + final CountingInputStream epilogueStream = new CountingInputStream(parser.getInputStream()); + epilogueStream.readAll(); + lines+=epilogueStream.getLineCount(); + } + propertyBuilder.setTextualLineCount(lines); } - } else { - propertyBuilder.setCharset(codeset); - } - - final String boundary = descriptor.getBoundary(); - if (boundary != null) { - propertyBuilder.setBoundary(boundary); - } - if ("text".equalsIgnoreCase(mediaType)) { - final CountingInputStream bodyStream = new CountingInputStream(parser.getInputStream()); - bodyStream.readAll(); - long lines = bodyStream.getLineCount(); - next = parser.next(); - if (next == MimeTokenStream.T_EPILOGUE) { - final CountingInputStream epilogueStream = new CountingInputStream(parser.getInputStream()); - epilogueStream.readAll(); - lines+=epilogueStream.getLineCount(); + final Flags flags; + if (flagsToBeSet == null) { + flags = new Flags(); + } else { + flags = flagsToBeSet; } - propertyBuilder.setTextualLineCount(lines); - } - - final Flags flags; - if (flagsToBeSet == null) { - flags = new Flags(); - } else { - flags = flagsToBeSet; - } - if (isRecent) { - flags.add(Flags.Flag.RECENT); - } - - final MailboxMembership<Id> message = createMessage(internalDate, uid, size, bodyStartOctet, new FileInputStream(file), flags, headers, propertyBuilder); - final MessageMapper<Id> mapper = createMessageMapper(mailboxSession); - - mapper.execute(new TransactionalMapper.Transaction() { - - public void run() throws MailboxException { - mapper.save(message); + if (isRecent) { + flags.add(Flags.Flag.RECENT); } - }); - dispatcher.added(uid, mailboxSession.getSessionId(), getMailboxRow(mailboxSession).getName()); - //tracker.found(uid, message.createFlags()); - return uid; - } catch (IOException e) { - e.printStackTrace(); - throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e); - } catch (MessagingException e) { - e.printStackTrace(); - throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e); - } catch (MimeException e) { - e.printStackTrace(); - throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e); - } finally { - // delete the temporary file if one was specified - if (file != null) { - file.delete(); + final MailboxMembership<Id> message = createMessage(internalDate, uid, size, bodyStartOctet, new FileInputStream(file), flags, headers, propertyBuilder); + mapper.save(message); + + + + dispatcher.added(uid, mailboxSession.getSessionId(), getMailboxRow(mailboxSession).getName()); + //tracker.found(uid, message.createFlags()); + uidHolder.add(uid); + } catch (IOException e) { + e.printStackTrace(); + throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e); + } catch (MessagingException e) { + e.printStackTrace(); + throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e); + } catch (MimeException e) { + e.printStackTrace(); + throw new MailboxException(HumanReadableText.FAILURE_MAIL_PARSE, e); + } finally { + // delete the temporary file if one was specified + if (file != null) { + file.delete(); + } } } - } + }); + + return uidHolder.get(0); } /** Modified: james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java URL: http://svn.apache.org/viewvc/james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java?rev=938618&r1=938617&r2=938618&view=diff ============================================================================== --- james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java (original) +++ james/imap/trunk/store/src/main/java/org/apache/james/imap/store/StoreMailboxManager.java Tue Apr 27 19:43:40 2010 @@ -22,10 +22,8 @@ package org.apache.james.imap.store; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.List; import java.util.Locale; -import java.util.Map; import java.util.Random; import org.apache.commons.logging.Log; @@ -65,17 +63,16 @@ public abstract class StoreMailboxManage public static final char SQL_WILDCARD_CHAR = '%'; + private final Object mutex = new Object(); + private final static Random random = new Random(); - protected final Map<String, StoreMailbox<Id>> mailboxes; private final MailboxEventDispatcher dispatcher = new MailboxEventDispatcher(); - + private final DelegatingMailboxListener delegatingListener = new DelegatingMailboxListener(); private final Authenticator authenticator; private final Subscriber subscriber; private final char delimiter; - - public final static String MAILBOX = "MAILBOX"; public StoreMailboxManager(final Authenticator authenticator, final Subscriber subscriber) { this(authenticator, subscriber, '.'); @@ -83,7 +80,6 @@ public abstract class StoreMailboxManage public StoreMailboxManager(final Authenticator authenticator, final Subscriber subscriber, final char delimiter) { - mailboxes = new HashMap<String, StoreMailbox<Id>>(); this.authenticator = authenticator; this.subscriber = subscriber; this.delimiter = delimiter; @@ -130,7 +126,7 @@ public abstract class StoreMailboxManage * @throws MailboxException get thrown if no Mailbox could be found for the given name */ private StoreMailbox<Id> doGetMailbox(String mailboxName, MailboxSession session) throws MailboxException { - synchronized (mailboxes) { + synchronized (mutex) { final MailboxMapper<Id> mapper = createMailboxMapper(session); Mailbox<Id> mailboxRow = mapper.findMailboxByName(mailboxName); @@ -141,14 +137,8 @@ public abstract class StoreMailboxManage } else { getLog().debug("Loaded mailbox " + mailboxName); - StoreMailbox<Id> result = (StoreMailbox<Id>) mailboxes.get(mailboxName); - if (result == null) { - result = createMailbox(dispatcher, mailboxRow); - mailboxes.put(mailboxName, result); - - // store the mailbox in the session so we can cleanup things later - //session.getAttributes().put(MAILBOX, result); - } + StoreMailbox<Id> result = createMailbox(dispatcher, mailboxRow); + result.addListener(delegatingListener); return result; } } @@ -167,7 +157,7 @@ public abstract class StoreMailboxManage } else if (namespaceName.charAt(length - 1) == delimiter) { createMailbox(namespaceName.substring(0, length - 1), mailboxSession); } else { - synchronized (mailboxes) { + synchronized (mutex) { // Create root first // If any creation fails then mailbox will not be created // TODO: transaction @@ -203,7 +193,7 @@ public abstract class StoreMailboxManage public void deleteMailbox(final String mailboxName, final MailboxSession session) throws MailboxException { session.getLog().info("deleteMailbox " + mailboxName); - synchronized (mailboxes) { + synchronized (mutex) { // TODO put this into a serilizable transaction final MailboxMapper<Id> mapper = createMailboxMapper(session); @@ -220,10 +210,6 @@ public abstract class StoreMailboxManage }); - final StoreMailbox<Id> storeMailbox = mailboxes.remove(mailboxName); - if (storeMailbox != null) { - //storeMailbox.deleted(session); - } dispatcher.mailboxDeleted(session.getSessionId(), mailboxName); } } @@ -236,7 +222,7 @@ public abstract class StoreMailboxManage throws MailboxException { final Log log = getLog(); if (log.isDebugEnabled()) log.debug("renameMailbox " + from + " to " + to); - synchronized (mailboxes) { + synchronized (mutex) { if (mailboxExists(to, session)) { throw new MailboxExistsException(to); } @@ -290,11 +276,6 @@ public abstract class StoreMailboxManage * @param to not null */ private void changeMailboxName(String from, String to, MailboxSession session) { - final StoreMailbox<Id> jpaMailbox = mailboxes.remove(from); - if (jpaMailbox != null) { - //jpaMailbox.reportRenamed(to); - } - mailboxes.put(to, jpaMailbox); dispatcher.mailboxRenamed(from, to, session.getSessionId()); } @@ -304,9 +285,12 @@ public abstract class StoreMailboxManage */ public void copyMessages(MessageRange set, String from, String to, MailboxSession session) throws MailboxException { + synchronized (mutex) { + StoreMailbox<Id> toMailbox = doGetMailbox(to, session); StoreMailbox<Id> fromMailbox = doGetMailbox(from, session); - fromMailbox.copyTo(set, toMailbox, session); + fromMailbox.copyTo(set, toMailbox, session); + } } /* @@ -368,11 +352,10 @@ public abstract class StoreMailboxManage * @see org.apache.james.imap.mailbox.MailboxManager#mailboxExists(java.lang.String, org.apache.james.imap.mailbox.MailboxSession) */ public boolean mailboxExists(String mailboxName, MailboxSession session) throws MailboxException { - synchronized (mailboxes) { + synchronized (mutex) { final MailboxMapper<Id> mapper = createMailboxMapper(session); final long count = mapper.countMailboxesWithName(mailboxName); if (count == 0) { - mailboxes.remove(mailboxName); return false; } else { if (count == 1) { @@ -472,8 +455,7 @@ public abstract class StoreMailboxManage * @see org.apache.james.imap.mailbox.MailboxManager#addListener(java.lang.String, org.apache.james.imap.mailbox.MailboxListener, org.apache.james.imap.mailbox.MailboxSession) */ public void addListener(String mailboxName, MailboxListener listener, MailboxSession session) throws MailboxException { - final StoreMailbox<Id> mailbox = doGetMailbox(mailboxName,session); - mailbox.addListener(listener); + delegatingListener.addListener(mailboxName, listener); } --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org