Index: torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailboxManager.java
===================================================================
--- torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailboxManager.java	(revision 67)
+++ torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailboxManager.java	(revision 69)
@@ -45,6 +45,8 @@
 import org.apache.torque.util.CountHelper;
 import org.apache.torque.util.Criteria;
 
+import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
+
 public class TorqueMailboxManager implements MailboxManager {
 
     private static Random random;
@@ -54,10 +56,13 @@
     
     protected Log log;
 
-    public TorqueMailboxManager(User authUser, MailboxCache mailboxCache, Log log) {
+    private final ReadWriteLock lock;
+    
+    public TorqueMailboxManager(User authUser, MailboxCache mailboxCache, final ReadWriteLock lock, Log log) {
         this.mailboxCache=mailboxCache;
         this.authUser=authUser;
         this.log=log;
+        this.lock = lock;
     }
     
     public MailboxSession getMailboxSession(String mailboxName,
@@ -109,8 +114,9 @@
                         getMailboxCache().add(mailboxName, tracker);
                     }
                     getLog().info("created ImapMailboxSession "+mailboxName);
-                    return new ImapMailboxSessionWrapper(new TorqueMailbox(
-                            mailboxRow, tracker,getLog()));
+                    final TorqueMailbox torqueMailbox = new TorqueMailbox(
+                                                mailboxRow, tracker,lock, getLog());
+                    return new ImapMailboxSessionWrapper(torqueMailbox);
                 } else {
                     getLog().info("Mailbox '" + mailboxName + "' not found.");
                     getMailboxCache().notFound(mailboxName);
Index: torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java
===================================================================
--- torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java	(revision 67)
+++ torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailbox.java	(revision 69)
@@ -59,6 +59,8 @@
 import org.apache.torque.TorqueException;
 import org.apache.torque.util.Criteria;
 
+import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
+
 import com.sun.mail.util.CRLFOutputStream;
 import com.workingdogs.village.DataSetException;
 
@@ -76,10 +78,13 @@
 
     private UidToKeyConverter uidToKeyConverter;
     
-    TorqueMailbox(MailboxRow mailboxRow, UidChangeTracker tracker, Log log) {
+    private final ReadWriteLock lock;
+    
+    TorqueMailbox(MailboxRow mailboxRow, UidChangeTracker tracker, final ReadWriteLock lock, Log log) {
         setLog(log);
         this.mailboxRow = mailboxRow;
         this.tracker = tracker;
+        this.lock = lock;
         tracker.addMailboxListener(getEventDispatcher());
         getUidToKeyConverter().setUidValidity(mailboxRow.getUidValidity());
     }
@@ -106,103 +111,126 @@
     }
 
     public int getMessageCount() throws MailboxManagerException {
-        long methodStartTime = System.currentTimeMillis();
+        try
+        {
+            lock.readLock().acquire();
+            try
+            {
+                long methodStartTime = System.currentTimeMillis();
                 checkAccess();
-        try {
-            final int countMessages = getMailboxRow().countMessages();
-            long duration = System.currentTimeMillis() - methodStartTime;
-            getLog().debug("getMessageCount took " + duration + "ms");
-            return countMessages;
-        } catch (Exception e) {
+                try {
+                    final int countMessages = getMailboxRow().countMessages();
+                    long duration = System.currentTimeMillis() - methodStartTime;
+                    getLog().debug("getMessageCount took " + duration + "ms");
+                    return countMessages;
+                } catch (Exception e) {
+                    throw new MailboxManagerException(e);
+                }
+            } finally {
+                lock.readLock().release();
+            }
+
+        } catch (InterruptedException e) {
             throw new MailboxManagerException(e);
         }
     }
 
     public MessageResult appendMessage(MimeMessage message, Date internalDate,
             int result) throws MailboxManagerException {
-        long methodStartTime = System.currentTimeMillis();
+        try
+        {
+            lock.writeLock().acquire();
+            try
+            {
+                long methodStartTime = System.currentTimeMillis();
                 checkAccess();
-        final MailboxRow myMailboxRow;
-        try {
-            myMailboxRow = getMailboxRow().consumeNextUid();
-        } catch (TorqueException e) {
-            throw new MailboxManagerException(e);
-        } catch (SQLException e) {
-            throw new MailboxManagerException(e);
-        }
-        if (myMailboxRow != null) {
-            try {
-                // 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
-                // insertet long before 4, when
-                // mail 4 is big and comes over a slow connection.
-                long uid = myMailboxRow.getLastUid();
-                this.mailboxRow = myMailboxRow;
+                final MailboxRow myMailboxRow;
+                try {
+                    myMailboxRow = getMailboxRow().consumeNextUid();
+                } catch (TorqueException e) {
+                    throw new MailboxManagerException(e);
+                } catch (SQLException e) {
+                    throw new MailboxManagerException(e);
+                }
+                if (myMailboxRow != null) {
+                    try {
+                        // 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
+                        // insertet long before 4, when
+                        // mail 4 is big and comes over a slow connection.
+                        long uid = myMailboxRow.getLastUid();
+                        this.mailboxRow = myMailboxRow;
 
-                MessageRow messageRow = new MessageRow();
-                messageRow.setMailboxId(getMailboxRow().getMailboxId());
-                messageRow.setUid(uid);
-                messageRow.setInternalDate(internalDate);
+                        MessageRow messageRow = new MessageRow();
+                        messageRow.setMailboxId(getMailboxRow().getMailboxId());
+                        messageRow.setUid(uid);
+                        messageRow.setInternalDate(internalDate);
 
-                // TODO very ugly size mesurement
-                ByteArrayOutputStream sizeBos = new ByteArrayOutputStream();
-                message.writeTo(new CRLFOutputStream(sizeBos));
-                messageRow.setSize(sizeBos.size());
-                MessageFlags messageFlags = new MessageFlags();
-                messageFlags.setFlags(message.getFlags());
-                messageRow.addMessageFlags(messageFlags);
+                        // TODO very ugly size mesurement
+                        ByteArrayOutputStream sizeBos = new ByteArrayOutputStream();
+                        message.writeTo(new CRLFOutputStream(sizeBos));
+                        messageRow.setSize(sizeBos.size());
+                        MessageFlags messageFlags = new MessageFlags();
+                        messageFlags.setFlags(message.getFlags());
+                        messageRow.addMessageFlags(messageFlags);
 
-                int line_number = 0;
+                        int line_number = 0;
 
-                for (Enumeration lines = message.getAllHeaderLines(); lines
+                        for (Enumeration lines = message.getAllHeaderLines(); lines
                         .hasMoreElements();) {
-                    String line = (String) lines.nextElement();
-                    int colon = line.indexOf(": ");
-                    if (colon > 0) {
-                        line_number++;
-                        MessageHeader mh = new MessageHeader();
-                        mh.setLineNumber(line_number);
-                        mh.setField(line.substring(0, colon));
-                        // TODO avoid unlikely IOOB Exception
-                        mh.setValue(line.substring(colon + 2));
-                        messageRow.addMessageHeader(mh);
-                    }
-                }
+                            String line = (String) lines.nextElement();
+                            int colon = line.indexOf(": ");
+                            if (colon > 0) {
+                                line_number++;
+                                MessageHeader mh = new MessageHeader();
+                                mh.setLineNumber(line_number);
+                                mh.setField(line.substring(0, colon));
+                                // TODO avoid unlikely IOOB Exception
+                                mh.setValue(line.substring(colon + 2));
+                                messageRow.addMessageHeader(mh);
+                            }
+                        }
 
-                MessageBody mb = new MessageBody();
+                        MessageBody mb = new MessageBody();
 
-                InputStream is = message.getInputStream();
+                        InputStream is = message.getInputStream();
 
-                ByteArrayOutputStream baos = new ByteArrayOutputStream();
-                byte[] buf = new byte[4096];
-                int read;
-                while ((read = is.read(buf)) > 0) {
-                    baos.write(buf, 0, read);
-                }
+                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+                        byte[] buf = new byte[4096];
+                        int read;
+                        while ((read = is.read(buf)) > 0) {
+                            baos.write(buf, 0, read);
+                        }
 
-                mb.setBody(baos.toByteArray());
-                messageRow.addMessageBody(mb);
+                        mb.setBody(baos.toByteArray());
+                        messageRow.addMessageBody(mb);
 
-                messageRow.save();
-                MessageResult messageResult = fillMessageResult(messageRow,
-                        result | MessageResult.UID);
-                checkForScanGap(uid);
-                getUidChangeTracker().found(messageResult, null);
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("appendMessage took " + duration + "ms");
-                return messageResult;
-            } catch (Exception e) {
-                throw new MailboxManagerException(e);
+                        messageRow.save();
+                        MessageResult messageResult = fillMessageResult(messageRow,
+                                result | MessageResult.UID);
+                        checkForScanGap(uid);
+                        getUidChangeTracker().found(messageResult, null);
+                        long duration = System.currentTimeMillis() - methodStartTime;
+                        getLog().debug("appendMessage took " + duration + "ms");
+                        return messageResult;
+                    } catch (Exception e) {
+                        throw new MailboxManagerException(e);
+                    }
+                } else {
+                    // mailboxRow==null
+                    getUidChangeTracker().mailboxNotFound();
+                    throw new MailboxManagerException("Mailbox has been deleted");
+                }
+            } finally {
+                lock.writeLock().release();
             }
-        } else {
-            // mailboxRow==null
-            getUidChangeTracker().mailboxNotFound();
-            throw new MailboxManagerException("Mailbox has been deleted");
+
+        } catch (InterruptedException e) {
+            throw new MailboxManagerException(e);
         }
-
     }
 
     private void checkForScanGap(long uid) throws MailboxManagerException, TorqueException, MessagingException {
@@ -264,29 +292,41 @@
 
     public MessageResult[] getMessages(GeneralMessageSet set, int result)
             throws MailboxManagerException {
-        long methodStartTime = System.currentTimeMillis();
+        try
+        {
+            lock.readLock().acquire();
+            try
+            {
+                long methodStartTime = System.currentTimeMillis();
                 checkAccess();
-        set=toUidSet(set);
-        if (!set.isValid() || set.getType()==GeneralMessageSet.TYPE_NOTHING) {
-            return new MessageResult[0];
-        }
-        UidRange range = uidRangeForMessageSet(set);
-        try {
-            Criteria c = criteriaForMessageSet(set);
-            c.add(MessageFlagsPeer.MAILBOX_ID,getMailboxRow().getMailboxId());
-            // TODO: this is bound to perform badly - classic case of non-performing generic interface
-            List l = MessageRowPeer.doSelectJoinMessageFlags(c);
-            MessageResult[] messageResults = fillMessageResult(l, result
-                    | MessageResult.UID | MessageResult.FLAGS);
-            checkForScanGap(range.getFromUid());
-            getUidChangeTracker().found(range, messageResults, null);
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("getMessages took " + duration + "ms");
-            return messageResults;
-        } catch (TorqueException e) {
+                set=toUidSet(set);
+                if (!set.isValid() || set.getType()==GeneralMessageSet.TYPE_NOTHING) {
+                    return new MessageResult[0];
+                }
+                UidRange range = uidRangeForMessageSet(set);
+                try {
+                    Criteria c = criteriaForMessageSet(set);
+                    c.add(MessageFlagsPeer.MAILBOX_ID,getMailboxRow().getMailboxId());
+                    // TODO: this is bound to perform badly - classic case of non-performing generic interface
+                    List l = MessageRowPeer.doSelectJoinMessageFlags(c);
+                    MessageResult[] messageResults = fillMessageResult(l, result
+                            | MessageResult.UID | MessageResult.FLAGS);
+                    checkForScanGap(range.getFromUid());
+                    getUidChangeTracker().found(range, messageResults, null);
+                    long duration = System.currentTimeMillis() - methodStartTime;
+                    getLog().debug("getMessages took " + duration + "ms");
+                    return messageResults;
+                } catch (TorqueException e) {
+                    throw new MailboxManagerException(e);
+                } catch (MessagingException e) {
+                    throw new MailboxManagerException(e);
+                }
+            } finally {
+                lock.readLock().release();
+            }
+
+        } catch (InterruptedException e) {
             throw new MailboxManagerException(e);
-        } catch (MessagingException e) {
-            throw new MailboxManagerException(e);
         }
 
     }
@@ -377,80 +417,133 @@
     }
 
     public int getRecentCount(boolean reset) throws MailboxManagerException {
-        long methodStartTime = System.currentTimeMillis();
+        try
+        {
+            lock.readLock().acquire();
+            try
+            {
+                long methodStartTime = System.currentTimeMillis();
                 checkAccess();
-        Flags flags = new Flags();
-        flags.add(Flags.Flag.RECENT);
-        try {
-            int count = getMailboxRow().countMessages(flags, true);
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("getRecentCount took " + duration + "ms");
-            return count;
-        } catch (TorqueException e) {
+                Flags flags = new Flags();
+                flags.add(Flags.Flag.RECENT);
+                try {
+                    int count = getMailboxRow().countMessages(flags, true);
+                    long duration = System.currentTimeMillis() - methodStartTime;
+                    getLog().debug("getRecentCount took " + duration + "ms");
+                    return count;
+                } catch (TorqueException e) {
+                    throw new MailboxManagerException(e);
+                } catch (DataSetException e) {
+                    throw new MailboxManagerException(e);
+                }
+            } finally {
+                lock.readLock().release();
+            }
+
+        } catch (InterruptedException e) {
             throw new MailboxManagerException(e);
-        } catch (DataSetException e) {
-            throw new MailboxManagerException(e);
         }
-
     }
 
     public MessageResult getFirstUnseen(int result)
             throws MailboxManagerException {
-        long methodStartTime = System.currentTimeMillis();
+        try
+        {
+            lock.readLock().acquire();
+            try
+            {
+                long methodStartTime = System.currentTimeMillis();
                 checkAccess();
-        Criteria c = new Criteria();
-        c.addAscendingOrderByColumn(MessageRowPeer.UID);
-        c.setLimit(1);
-        c.setSingleRecord(true);
-        
-        c.addJoin(MessageFlagsPeer.MAILBOX_ID, MessageRowPeer.MAILBOX_ID);
-        c.addJoin(MessageRowPeer.UID, MessageFlagsPeer.UID);
-        
-        MessageFlagsPeer.addFlagsToCriteria(new Flags(Flags.Flag.SEEN), false,
-                c);
-        
-        try {
-            List messageRows = getMailboxRow().getMessageRows(c);
-            if (messageRows.size() > 0) {
-                MessageResult messageResult=fillMessageResult((MessageRow) messageRows.get(0), result | MessageResult.UID);
-                if (messageResult!=null) {
-                    checkForScanGap(messageResult.getUid());
-                    getUidChangeTracker().found(messageResult,null);
+                Criteria c = new Criteria();
+                c.addAscendingOrderByColumn(MessageRowPeer.UID);
+                c.setLimit(1);
+                c.setSingleRecord(true);
+
+                c.addJoin(MessageFlagsPeer.MAILBOX_ID, MessageRowPeer.MAILBOX_ID);
+                c.addJoin(MessageRowPeer.UID, MessageFlagsPeer.UID);
+
+                MessageFlagsPeer.addFlagsToCriteria(new Flags(Flags.Flag.SEEN), false,
+                        c);
+
+                try {
+                    List messageRows = getMailboxRow().getMessageRows(c);
+                    if (messageRows.size() > 0) {
+                        MessageResult messageResult=fillMessageResult((MessageRow) messageRows.get(0), result | MessageResult.UID);
+                        if (messageResult!=null) {
+                            checkForScanGap(messageResult.getUid());
+                            getUidChangeTracker().found(messageResult,null);
+                        }
+                        long duration = System.currentTimeMillis() - methodStartTime;
+                        getLog().debug("getFirstUnseen took " + duration + "ms");
+
+                        return messageResult;
+                    } else {
+                        return null;
+                    }
+                } catch (TorqueException e) {
+                    throw new MailboxManagerException(e);
+                } catch (MessagingException e) {
+                    throw new MailboxManagerException(e);
                 }
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("getFirstUnseen took " + duration + "ms");
-                
-                return messageResult;
-            } else {
-                return null;
+            } finally {
+                lock.readLock().release();
             }
-        } catch (TorqueException e) {
+
+        } catch (InterruptedException e) {
             throw new MailboxManagerException(e);
-        } catch (MessagingException e) {
-            throw new MailboxManagerException(e);
         }
-
     }
 
     public int getUnseenCount() throws MailboxManagerException {
-        long methodStartTime = System.currentTimeMillis();
+        try
+        {
+            lock.readLock().acquire();
+            try
+            {
+                long methodStartTime = System.currentTimeMillis();
                 checkAccess();
-        try {
-            final int count = getMailboxRow().countMessages(new Flags(Flags.Flag.SEEN), false);
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("getUnseenCount took " + duration + "ms");
-            return count;
-        } catch (TorqueException e) {
+                try {
+                    final int count = getMailboxRow().countMessages(new Flags(Flags.Flag.SEEN), false);
+                    long duration = System.currentTimeMillis() - methodStartTime;
+                    getLog().debug("getUnseenCount took " + duration + "ms");
+                    return count;
+                } catch (TorqueException e) {
+                    throw new MailboxManagerException(e);
+                } catch (DataSetException e) {
+                    throw new MailboxManagerException(e);
+                }
+            } finally {
+                lock.readLock().release();
+            }
+
+        } catch (InterruptedException e) {
             throw new MailboxManagerException(e);
-        } catch (DataSetException e) {
-            throw new MailboxManagerException(e);
         }
     }
 
     public MessageResult[] expunge(GeneralMessageSet set, int result)
             throws MailboxManagerException {
+        try
+        {
+            lock.writeLock().acquire();
+            try
+            {
+                return doExpunge(set, result);
+            } finally {
+                lock.writeLock().release();
+            }
+
+        } catch (InterruptedException e) {
+            throw new MailboxManagerException(e);
+        }
+    }
+
+    /**
+     * Unlocked version of {@link #expunge(GeneralMessageSet, int).
+     */
+    private MessageResult[] doExpunge(GeneralMessageSet set, int result) throws MailboxManagerException {
         long methodStartTime = System.currentTimeMillis();
-                checkAccess();
+        checkAccess();
         set=toUidSet(set);  
         if (!set.isValid() || set.getType()==GeneralMessageSet.TYPE_NOTHING) {
             return new MessageResult[0];
@@ -475,8 +568,8 @@
                 MessageRowPeer.doDelete(todelc);
             }
             getUidChangeTracker().expunged(messageResults);
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("expunge took " + duration + "ms");
+            long duration = System.currentTimeMillis() - methodStartTime;
+            getLog().debug("expunge took " + duration + "ms");
             return messageResults;
         } catch (Exception e) {
             throw new MailboxManagerException(e);
@@ -485,9 +578,25 @@
 
     public void setFlags(Flags flags, boolean value, boolean replace,
             GeneralMessageSet set, MailboxListener silentListener)
-            throws MailboxManagerException {
+    throws MailboxManagerException {
+        try
+        {
+            lock.writeLock().acquire();
+            try
+            {
+                doSetFlags(flags, value, replace, set, silentListener);            
+            } finally {
+                lock.writeLock().release();
+            }
+
+        } catch (InterruptedException e) {
+            throw new MailboxManagerException(e);
+        }
+    }
+
+    private void doSetFlags(Flags flags, boolean value, boolean replace, GeneralMessageSet set, MailboxListener silentListener) throws MailboxManagerException {
         long methodStartTime = System.currentTimeMillis();
-                checkAccess();
+        checkAccess();
         set=toUidSet(set);  
         if (!set.isValid() || set.getType()==GeneralMessageSet.TYPE_NOTHING) {
             return;
@@ -495,7 +604,7 @@
         try {
             // TODO put this into a serializeable transaction
             final List messageRows = getMailboxRow()
-                    .getMessageRows(criteriaForMessageSet(set));
+            .getMessageRows(criteriaForMessageSet(set));
             final MessageResult[] beforeResults = fillMessageResult(messageRows,
                     MessageResult.UID | MessageResult.FLAGS);
             UidRange uidRange=uidRangeForMessageSet(set);
@@ -522,8 +631,8 @@
             final MessageResult[] afterResults = fillMessageResult(messageRows,
                     MessageResult.UID | MessageResult.FLAGS);
             tracker.found(uidRange, afterResults, silentListener);
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("setFlags took " + duration + "ms");
+            long duration = System.currentTimeMillis() - methodStartTime;
+            getLog().debug("setFlags took " + duration + "ms");
         } catch (Exception e) {
             throw new MailboxManagerException(e);
         }
@@ -551,38 +660,62 @@
         getLog().debug("removeListener took " + duration + "ms");        
     }
 
-    public synchronized long getUidValidity() throws MailboxManagerException {
-        final long uidValidity;
-        long methodStartTime = System.currentTimeMillis();
-        checkAccess();
-        uidValidity = getMailboxRow().getUidValidity();
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("getUidValidity took " + duration + "ms");        
-        return uidValidity;
+    public long getUidValidity() throws MailboxManagerException {
+        try
+        {
+            lock.writeLock().acquire();
+            try
+            {
+                final long uidValidity;
+                long methodStartTime = System.currentTimeMillis();
+                checkAccess();
+                uidValidity = getMailboxRow().getUidValidity();
+                long duration = System.currentTimeMillis() - methodStartTime;
+                getLog().debug("getUidValidity took " + duration + "ms");        
+                return uidValidity;
+            } finally {
+                lock.writeLock().release();
+            }
+
+        } catch (InterruptedException e) {
+            throw new MailboxManagerException(e);
+        }
     }
 
-    public synchronized long getUidNext() throws MailboxManagerException {
-        long methodStartTime = System.currentTimeMillis();
+    public long getUidNext() throws MailboxManagerException {
+        try
+        {
+            lock.writeLock().acquire();
+            try
+            {
+                long methodStartTime = System.currentTimeMillis();
                 checkAccess();
-        try {
-            MailboxRow myMailboxRow = MailboxRowPeer.retrieveByPK(mailboxRow.getPrimaryKey());
-            if (myMailboxRow != null) {
-                mailboxRow=myMailboxRow;
-                getUidChangeTracker().foundLastUid(mailboxRow.getLastUid());
-                final long result = getUidChangeTracker().getLastUid() + 1;
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("getUidNext took " + duration + "ms");
-                return result;
-            } else {
-                getUidChangeTracker().mailboxNotFound();
-                throw new MailboxManagerException("Mailbox has been deleted");
+                try {
+                    MailboxRow myMailboxRow = MailboxRowPeer.retrieveByPK(mailboxRow.getPrimaryKey());
+                    if (myMailboxRow != null) {
+                        mailboxRow=myMailboxRow;
+                        getUidChangeTracker().foundLastUid(mailboxRow.getLastUid());
+                        final long result = getUidChangeTracker().getLastUid() + 1;
+                        long duration = System.currentTimeMillis() - methodStartTime;
+                        getLog().debug("getUidNext took " + duration + "ms");
+                        return result;
+                    } else {
+                        getUidChangeTracker().mailboxNotFound();
+                        throw new MailboxManagerException("Mailbox has been deleted");
+                    }
+                } catch (NoRowsException e) {
+                    throw new MailboxManagerException(e);
+                } catch (TooManyRowsException e) {
+                    throw new MailboxManagerException(e);
+                } catch (TorqueException e) {
+                    throw new MailboxManagerException(e);
+                }
+            } finally {
+                lock.writeLock().release();
             }
-        } catch (NoRowsException e) {
+
+        } catch (InterruptedException e) {
             throw new MailboxManagerException(e);
-        } catch (TooManyRowsException e) {
-            throw new MailboxManagerException(e);
-        } catch (TorqueException e) {
-            throw new MailboxManagerException(e);
         }
     }
 
@@ -621,18 +754,30 @@
 
     public MessageResult[] search(GeneralMessageSet set, SearchTerm searchTerm,
             int result) throws MailboxManagerException {
-        MessageResult[] results={};
-        long methodStartTime = System.currentTimeMillis();
-        checkAccess();set=toUidSet(set);if (!set.isValid() || set.getType()==GeneralMessageSet.TYPE_NOTHING) {
-            return new MessageResult[0];
+        try
+        {
+            lock.readLock().acquire();
+            try
+            {
+                MessageResult[] results={};
+                long methodStartTime = System.currentTimeMillis();
+                checkAccess();set=toUidSet(set);if (!set.isValid() || set.getType()==GeneralMessageSet.TYPE_NOTHING) {
+                    return new MessageResult[0];
+                }
+                final Log log = getLog();// TODO implementation
+                if (log.isWarnEnabled()) {
+                    log.warn("Search is not yet implemented. Sorry.");
+                }
+                long duration = System.currentTimeMillis() - methodStartTime;
+                getLog().debug("search took " + duration + "ms");        
+                return results;
+            } finally {
+                lock.readLock().release();
+            }
+
+        } catch (InterruptedException e) {
+            throw new MailboxManagerException(e);
         }
-        final Log log = getLog();// TODO implementation
-        if (log.isWarnEnabled()) {
-            log.warn("Search is not yet implemented. Sorry.");
-        }
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("search took " + duration + "ms");        
-        return results;
     }
     
     protected UidToKeyConverter getUidToKeyConverter() {
@@ -643,11 +788,23 @@
     }
 
     public void remove(GeneralMessageSet set) throws MailboxManagerException {
-        long methodStartTime = System.currentTimeMillis();
-        setFlags(new Flags(Flags.Flag.DELETED), true, false, set, null);
-        expunge(set, MessageResult.NOTHING);
-        long duration = System.currentTimeMillis() - methodStartTime;
-        getLog().debug("remove took " + duration + "ms");        
+        try
+        {
+            lock.writeLock().acquire();
+            try
+            {
+                long methodStartTime = System.currentTimeMillis();
+                doSetFlags(new Flags(Flags.Flag.DELETED), true, false, set, null);
+                doExpunge(set, MessageResult.NOTHING);
+                long duration = System.currentTimeMillis() - methodStartTime;
+                getLog().debug("remove took " + duration + "ms");    
+            } finally {
+                lock.writeLock().release();
+            }
+
+        } catch (InterruptedException e) {
+            throw new MailboxManagerException(e);
+        }
     }
 
     private GeneralMessageSet toUidSet(GeneralMessageSet set) {
Index: torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailboxManagerFactory.java
===================================================================
--- torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailboxManagerFactory.java	(revision 67)
+++ torque-mailboxmanager-function/src/main/java/org/apache/james/mailboxmanager/torque/TorqueMailboxManagerFactory.java	(revision 69)
@@ -62,6 +62,9 @@
 import org.apache.torque.util.BasePeer;
 import org.apache.torque.util.Transaction;
 
+import EDU.oswego.cs.dl.util.concurrent.ReadWriteLock;
+import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock;
+
 public class TorqueMailboxManagerFactory implements MailboxManagerFactory,
         Configurable, Initializable, Serviceable, LogEnabled {
 
@@ -75,17 +78,23 @@
 
     private FileSystem fileSystem;
 
+    private final ReadWriteLock lock;
+    
     private static final String[] tableNames = new String[] {
             MailboxRowPeer.TABLE_NAME, MessageRowPeer.TABLE_NAME,
             MessageHeaderPeer.TABLE_NAME, MessageBodyPeer.TABLE_NAME,
             MessageFlagsPeer.TABLE_NAME };
 
+    public TorqueMailboxManagerFactory() {
+        lock = new WriterPreferenceReadWriteLock();
+    }
+    
     public MailboxManager getMailboxManagerInstance(User user)
             throws MailboxManagerException {
         if (!initialized) {
             throw new MailboxManagerException("must be initialized first!");
         }
-        return new TorqueMailboxManager(user, getMailboxCache(), getLog());
+        return new TorqueMailboxManager(user, getMailboxCache(), lock, getLog());
     }
 
     public void initialize() throws Exception {
Index: phoenix-deployment/src/test/org/apache/james/mailboxmanager/torque/TorqueMailboxTestCase.java
===================================================================
--- phoenix-deployment/src/test/org/apache/james/mailboxmanager/torque/TorqueMailboxTestCase.java	(revision 67)
+++ phoenix-deployment/src/test/org/apache/james/mailboxmanager/torque/TorqueMailboxTestCase.java	(revision 69)
@@ -18,6 +18,8 @@
 import org.apache.torque.TorqueException;
 import org.apache.torque.util.Criteria;
 
+import EDU.oswego.cs.dl.util.concurrent.WriterPreferenceReadWriteLock;
+
 public class TorqueMailboxTestCase extends AbstractTorqueTestCase {
 
 
@@ -29,7 +31,7 @@
         MailboxRow mr = new MailboxRow("#users.tuser.INBOX", 100);
         mr.save();
         mr=MailboxRowPeer.retrieveByName("#users.tuser.INBOX");
-        TorqueMailbox torqueMailbox = new TorqueMailbox(mr, new UidChangeTracker(null,"#users.tuser.INBOX",100),null);
+        TorqueMailbox torqueMailbox = new TorqueMailbox(mr, new UidChangeTracker(null,"#users.tuser.INBOX",100),new WriterPreferenceReadWriteLock(), null);
         torqueMailbox.addListener(new MailboxListenerCollector(), MessageResult.NOTHING);
         assertEquals(0,torqueMailbox.getMessageCount());
         
