You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by no...@apache.org on 2011/05/25 19:33:32 UTC

svn commit: r1127594 [1/2] - in /james/mailbox/trunk: api/src/main/java/org/apache/james/mailbox/ api/src/main/java/org/apache/james/mailbox/util/ api/src/test/java/org/apache/james/mailbox/mock/ api/src/test/java/org/apache/james/mailbox/util/ jcr/src...

Author: norman
Date: Wed May 25 17:33:30 2011
New Revision: 1127594

URL: http://svn.apache.org/viewvc?rev=1127594&view=rev
Log:
Add support for a mod-sequence per message. Also merge the UidProvider with MessageMapper as it belongs there. See MAILBOX-74

Added:
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/mail/AbstractMessageMapper.java
Removed:
    james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/JCRCachingUidProvider.java
    james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPACachingUidProvider.java
    james/mailbox/trunk/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryCachingUidProvider.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/mail/CachingUidProvider.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/mail/UidProvider.java
Modified:
    james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageManager.java
    james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageMetaData.java
    james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/SearchQuery.java
    james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/UpdatedFlags.java
    james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/util/MessageResultImpl.java
    james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/mock/MockMailboxSession.java
    james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/util/MailboxEventDispatcherFlagsTest.java
    james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMailboxManager.java
    james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java
    james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/JCRMessageMapper.java
    james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/model/JCRMessage.java
    james/mailbox/trunk/jcr/src/main/resources/org/apache/james/mailbox/jcr/imap.cnd
    james/mailbox/trunk/jcr/src/test/java/org/apache/james/mailbox/jcr/JCRMailboxManagerTest.java
    james/mailbox/trunk/jcr/src/test/java/org/apache/james/mailbox/jcr/JCRStressTest.java
    james/mailbox/trunk/jpa/pom.xml
    james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxManager.java
    james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java
    james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java
    james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMessage.java
    james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAMessage.java
    james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAStreamingMessage.java
    james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMailboxManager.java
    james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java
    james/mailbox/trunk/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java
    james/mailbox/trunk/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAStressTest.java
    james/mailbox/trunk/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirFolder.java
    james/mailbox/trunk/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirMailboxManager.java
    james/mailbox/trunk/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirMessageManager.java
    james/mailbox/trunk/maildir/src/main/java/org/apache/james/mailbox/maildir/MaildirStore.java
    james/mailbox/trunk/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/MaildirMessageMapper.java
    james/mailbox/trunk/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/AbstractMaildirMessage.java
    james/mailbox/trunk/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/LazyLoadingMaildirMessage.java
    james/mailbox/trunk/maildir/src/main/java/org/apache/james/mailbox/maildir/mail/model/MaildirMessage.java
    james/mailbox/trunk/maildir/src/test/java/org/apache/james/mailbox/maildir/MaildirMailboxManagerTest.java
    james/mailbox/trunk/maildir/src/test/java/org/apache/james/mailbox/maildir/MaildirStressTest.java
    james/mailbox/trunk/memory/src/main/java/org/apache/james/mailbox/inmemory/InMemoryMailboxManager.java
    james/mailbox/trunk/memory/src/main/java/org/apache/james/mailbox/inmemory/InMemoryStoreMessageManager.java
    james/mailbox/trunk/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMailboxMapper.java
    james/mailbox/trunk/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/InMemoryMessageMapper.java
    james/mailbox/trunk/memory/src/main/java/org/apache/james/mailbox/inmemory/mail/model/SimpleMailboxMembership.java
    james/mailbox/trunk/memory/src/test/java/org/apache/james/mailbox/inmemory/InMemoryMailboxManagerTest.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/MailboxMetaData.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/MessageSearches.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/ResultIterator.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/ResultUtils.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMailboxManager.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/StoreMessageManager.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/mail/MessageMapper.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/mail/SimpleMessageMetaData.java
    james/mailbox/trunk/store/src/main/java/org/apache/james/mailbox/store/mail/model/Message.java
    james/mailbox/trunk/store/src/test/java/org/apache/james/mailbox/store/MessageBuilder.java
    james/mailbox/trunk/store/src/test/java/org/apache/james/mailbox/store/SimpleMailboxMembership.java
    james/mailbox/trunk/store/src/test/java/org/apache/james/mailbox/store/lucene/LuceneMessageSearchIndexTest.java
    james/mailbox/trunk/tool/src/test/java/org/apache/james/mailbox/copier/MailboxCopierTest.java

Modified: james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageManager.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageManager.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageManager.java (original)
+++ james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageManager.java Wed May 25 17:33:30 2011
@@ -215,11 +215,17 @@ public interface MessageManager {
          * the one that is assigned to the next message. Its only guaranteed
          * that it will be at least equals or bigger then the value
          * 
-         * @param mailboxSession
-         *            not null
          * @return the uid that will be assigned to the next appended message
          */
         long getUidNext();
+        
+        /**
+         * Return the highest mod-sequence for the mailbox. If this value has changed
+         * till the last check you can be sure that some changes where happen on the mailbox
+         * 
+         * @return higestModSeq
+         */
+        long getHighestModSeq();
 
         /**
          * Gets the number of messages that this mailbox contains.

Modified: james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageMetaData.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageMetaData.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageMetaData.java (original)
+++ james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/MessageMetaData.java Wed May 25 17:33:30 2011
@@ -35,6 +35,15 @@ public interface MessageMetaData {
      * @return uid
      */
     long getUid();
+    
+    
+    /**
+     * Return the modify-sequence number of the message. This is kind of optional and the mailbox
+     * implementation may not support this. If so it will return -1
+     * 
+     * @return modSeq
+     */
+    long getModSeq();
 
     /**
      * Return the {@link Flags} 

Modified: james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/SearchQuery.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/SearchQuery.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/SearchQuery.java (original)
+++ james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/SearchQuery.java Wed May 25 17:33:30 2011
@@ -132,6 +132,42 @@ public class SearchQuery {
     }
 
     /**
+     * Creates a filter for message mod-sequence less than the given value
+     * 
+     * @param value
+     *            messages with mod-sequence less than this value will be selected by
+     *            the returned criterion
+     * @return <code>Criterion</code>, not null
+     */
+    public static final Criterion modSeqLessThan(long value) {
+        return new ModSeqCriterion(new NumericOperator(value, NumericComparator.LESS_THAN));
+    }
+
+    /**
+     * Creates a filter for message mod-sequence greater than the given value
+     * 
+     * @param value
+     *            messages with mod-sequence greater than this value will be selected by
+     *            the returned criterion
+     * @return <code>Criterion</code>, not null
+     */
+    public static final Criterion modSeqGreaterThan(long value) {
+        return new ModSeqCriterion(new NumericOperator(value, NumericComparator.GREATER_THAN));
+    }
+
+    /**
+     * Creates a filter for message mod-sequence equal to the given value
+     * 
+     * @param value
+     *            messages with mod-sequence equal to this value will be selected by the
+     *            returned criterion
+     * @return <code>Criterion</code>, not null
+     */
+    public static final Criterion modSeqEquals(long value) {
+        return new ModSeqCriterion(new NumericOperator(value, NumericComparator.EQUALS));
+    }
+    
+    /**
      * Creates a filter matching messages with internal date after the given
      * date.
      * 
@@ -996,8 +1032,73 @@ public class SearchQuery {
     }
 
     /**
-     * Filters on the size of the message in octets.
+     * Filters on the mod-sequence of the messages.
      */
+    public static final class ModSeqCriterion extends Criterion {
+        private final NumericOperator operator;
+
+        private ModSeqCriterion(final NumericOperator operator) {
+            super();
+            this.operator = operator;
+        }
+
+        /**
+         * Gets the search operation and value to be evaluated.
+         * 
+         * @return the <code>NumericOperator</code>, not null
+         */
+        public NumericOperator getOperator() {
+            return operator;
+        }
+
+        /**
+         * @see java.lang.Object#hashCode()
+         */
+        @Override
+        public int hashCode() {
+            final int PRIME = 31;
+            int result = 1;
+            result = PRIME * result + ((operator == null) ? 0 : operator.hashCode());
+            return result;
+        }
+
+        /**
+         * @see java.lang.Object#equals(java.lang.Object)
+         */
+        @Override
+        public boolean equals(Object obj) {
+            if (this == obj)
+                return true;
+            if (obj == null)
+                return false;
+            if (getClass() != obj.getClass())
+                return false;
+            final ModSeqCriterion other = (ModSeqCriterion) obj;
+            if (operator == null) {
+                if (other.operator != null)
+                    return false;
+            } else if (!operator.equals(other.operator))
+                return false;
+            return true;
+        }
+
+        /**
+         * Constructs a <code>String</code> with all attributes in name = value
+         * format.
+         * 
+         * @return a <code>String</code> representation of this object.
+         */
+        public String toString() {
+            final String TAB = " ";
+
+            StringBuffer retValue = new StringBuffer();
+
+            retValue.append("SizeCriterion ( ").append("operator = ").append(this.operator).append(TAB).append(" )");
+
+            return retValue.toString();
+        }
+    }
+
     public static final class SizeCriterion extends Criterion {
         private final NumericOperator operator;
 
@@ -1063,6 +1164,7 @@ public class SearchQuery {
         }
     }
 
+    
     /**
      * Filters on a custom flag valuation.
      */

Modified: james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/UpdatedFlags.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/UpdatedFlags.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/UpdatedFlags.java (original)
+++ james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/UpdatedFlags.java Wed May 25 17:33:30 2011
@@ -35,17 +35,19 @@ public class UpdatedFlags {
     private final Flags oldFlags;
     private final Flags newFlags;
     private final Flags modifiedFlags;
+    private long modSeq;
 
-    public UpdatedFlags(long uid, Flags oldFlags, Flags newFlags) {
+    public UpdatedFlags(long uid, long modSeq, Flags oldFlags, Flags newFlags) {
        this.uid = uid;
+       this.modSeq = modSeq;
        this.oldFlags = oldFlags;
        this.newFlags = newFlags;
        this.modifiedFlags = new Flags();
-       addModifiedSystemFlags();
-       addModifiedUserFlags();
+       addModifiedSystemFlags(oldFlags, newFlags, modifiedFlags);
+       addModifiedUserFlags(oldFlags, newFlags, modifiedFlags);
     }
     
-    private void addModifiedSystemFlags() {
+    private static void addModifiedSystemFlags(Flags oldFlags, Flags newFlags, Flags modifiedFlags) {
         if (isChanged(oldFlags, newFlags, Flags.Flag.ANSWERED)) {
             modifiedFlags.add(Flags.Flag.ANSWERED);
         }
@@ -66,14 +68,14 @@ public class UpdatedFlags {
         }
     }
     
-    private void addModifiedUserFlags() {
-        addModifiedUserFlags(oldFlags.getUserFlags());
-        addModifiedUserFlags(newFlags.getUserFlags());
+    private static void addModifiedUserFlags(Flags oldFlags, Flags newFlags, Flags modifiedFlags) {
+        addModifiedUserFlags(oldFlags, newFlags, oldFlags.getUserFlags(), modifiedFlags);
+        addModifiedUserFlags(oldFlags, newFlags, newFlags.getUserFlags(), modifiedFlags);
 
     }
     
 
-    private void addModifiedUserFlags(String[] userflags) {
+    private static void addModifiedUserFlags(Flags oldFlags, Flags newFlags, String[] userflags, Flags modifiedFlags) {
         for (int i = 0; i < userflags.length; i++) {
             String userFlag = userflags[i];
             if (isChanged(oldFlags, newFlags, userFlag)) {
@@ -138,4 +140,25 @@ public class UpdatedFlags {
     public Iterator<String> userFlagIterator() {
         return Arrays.asList(modifiedFlags.getUserFlags()).iterator();
     }
+    
+    
+    /**
+     * Return the new mod-sequence for the message
+     * 
+     * @return mod-seq
+     */
+    public long getModSeq() {
+        return modSeq;
+    }
+    
+    public static boolean flagsChanged(Flags flagsOld, Flags flagsNew) {
+        Flags modifiedFlags = new Flags();
+        addModifiedSystemFlags(flagsOld, flagsNew, modifiedFlags);
+        addModifiedUserFlags(flagsOld, flagsNew, modifiedFlags);
+        if (modifiedFlags.getSystemFlags().length > 0 || modifiedFlags.getUserFlags().length > 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
 }

Modified: james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/util/MessageResultImpl.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/util/MessageResultImpl.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/util/MessageResultImpl.java (original)
+++ james/mailbox/trunk/api/src/main/java/org/apache/james/mailbox/util/MessageResultImpl.java Wed May 25 17:33:30 2011
@@ -56,6 +56,8 @@ public class MessageResultImpl implement
 
     private MimeDescriptor mimeDescriptor;
 
+    private long modSeq;
+
     public MessageResultImpl(long uid) {
         setUid(uid);
     }
@@ -67,6 +69,8 @@ public class MessageResultImpl implement
         setUid(uid);
         setFlags(flags);
     }
+    
+    
 
     /*
      * (non-Javadoc)
@@ -404,4 +408,16 @@ public class MessageResultImpl implement
     public MimeDescriptor getMimeDescriptor() {
         return mimeDescriptor;
     }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.mailbox.MessageMetaData#getModSeq()
+     */
+    public long getModSeq() {
+        return modSeq;
+    }
+    
+    public void setModSeq(long modSeq) {
+        this.modSeq = modSeq;
+    }
 }

Modified: james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/mock/MockMailboxSession.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/mock/MockMailboxSession.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/mock/MockMailboxSession.java (original)
+++ james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/mock/MockMailboxSession.java Wed May 25 17:33:30 2011
@@ -26,9 +26,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Random;
 
-import org.apache.james.mailbox.MailboxConstants;
 import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.MailboxSession.User;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 

Modified: james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/util/MailboxEventDispatcherFlagsTest.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/util/MailboxEventDispatcherFlagsTest.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/util/MailboxEventDispatcherFlagsTest.java (original)
+++ james/mailbox/trunk/api/src/test/java/org/apache/james/mailbox/util/MailboxEventDispatcherFlagsTest.java Wed May 25 17:33:30 2011
@@ -77,7 +77,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldReturnNoChangesWhenSystemFlagsUnchanged() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1,  new Flags(
                 Flags.Flag.DELETED), new Flags(Flags.Flag.DELETED))));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -90,7 +90,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowAnsweredAdded() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(),
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(),
                 new Flags(Flags.Flag.ANSWERED))));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -105,7 +105,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowAnsweredRemoved() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(
                 Flags.Flag.ANSWERED), new Flags())));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -120,7 +120,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowDeletedAdded() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(),
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(),
                 new Flags(Flags.Flag.DELETED))));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -135,7 +135,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowDeletedRemoved() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(
                 Flags.Flag.DELETED), new Flags())));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -150,7 +150,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowDraftAdded() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(),
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(),
                 new Flags(Flags.Flag.DRAFT))));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -165,7 +165,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowDraftRemoved() {
-        dispatcher.flagsUpdated(session,Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(
+        dispatcher.flagsUpdated(session,Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(
                 Flags.Flag.DRAFT), new Flags())));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -180,7 +180,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowFlaggedAdded() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(),
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(),
                 new Flags(Flags.Flag.FLAGGED))));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -195,7 +195,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowFlaggedRemoved() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(
                 Flags.Flag.FLAGGED), new Flags())));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -210,7 +210,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowRecentAdded() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(),
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(),
                 new Flags(Flags.Flag.RECENT))));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -225,7 +225,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowRecentRemoved() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(
                 Flags.Flag.RECENT), new Flags())));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -240,7 +240,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowSeenAdded() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(),
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(),
                 new Flags(Flags.Flag.SEEN))));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -255,7 +255,7 @@ public class MailboxEventDispatcherFlags
 
     @Test
     public void testShouldShowSeenRemoved() {
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), new Flags(
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, new Flags(
                 Flags.Flag.SEEN), new Flags())));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
@@ -278,7 +278,7 @@ public class MailboxEventDispatcherFlags
         updated.add(Flags.Flag.DRAFT);
         updated.add(Flags.Flag.SEEN);
 
-        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), originals, updated)));
+        dispatcher.flagsUpdated(session, Arrays.asList(result.getUid()), path, Arrays.asList(new UpdatedFlags(result.getUid(), -1, originals, updated)));
         assertEquals(1, collector.events.size());
         assertTrue(collector.events.get(0) instanceof MailboxListener.FlagsUpdated);
         MailboxListener.FlagsUpdated event = (MailboxListener.FlagsUpdated) collector.events

Modified: james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMailboxManager.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMailboxManager.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMailboxManager.java (original)
+++ james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMailboxManager.java Wed May 25 17:33:30 2011
@@ -27,7 +27,6 @@ import org.apache.james.mailbox.store.Au
 import org.apache.james.mailbox.store.JVMMailboxPathLocker;
 import org.apache.james.mailbox.store.StoreMailboxManager;
 import org.apache.james.mailbox.store.StoreMessageManager;
-import org.apache.james.mailbox.store.mail.UidProvider;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.util.MailboxEventDispatcher;
 import org.slf4j.Logger;
@@ -42,19 +41,19 @@ public class JCRMailboxManager extends S
     private final JCRMailboxSessionMapperFactory mapperFactory;
     private final Logger logger = LoggerFactory.getLogger(JCRMailboxManager.class);
     
-    public JCRMailboxManager(JCRMailboxSessionMapperFactory mapperFactory, final Authenticator authenticator, final UidProvider<String> uidProvider) {
-	    this(mapperFactory, authenticator, uidProvider, new JVMMailboxPathLocker());
+    public JCRMailboxManager(JCRMailboxSessionMapperFactory mapperFactory, final Authenticator authenticator) {
+	    this(mapperFactory, authenticator, new JVMMailboxPathLocker());
     }
 
-    public JCRMailboxManager(JCRMailboxSessionMapperFactory mapperFactory, final Authenticator authenticator, final UidProvider<String> uidProvider, final MailboxPathLocker locker) {
-        super(mapperFactory, authenticator, uidProvider, locker);
+    public JCRMailboxManager(JCRMailboxSessionMapperFactory mapperFactory, final Authenticator authenticator, final MailboxPathLocker locker) {
+        super(mapperFactory, authenticator, locker);
         this.mapperFactory = mapperFactory;
     }
 
     
     @Override
-    protected StoreMessageManager<String> createMessageManager(UidProvider<String> uidProvider, MailboxEventDispatcher dispatcher, Mailbox<String> mailboxEntity, MailboxSession session) throws MailboxException{
-        return new JCRMessageManager(mapperFactory, uidProvider, dispatcher, (JCRMailbox) mailboxEntity, logger, getDelimiter());
+    protected StoreMessageManager<String> createMessageManager(MailboxEventDispatcher dispatcher, Mailbox<String> mailboxEntity, MailboxSession session) throws MailboxException{
+        return new JCRMessageManager(mapperFactory, dispatcher, (JCRMailbox) mailboxEntity, logger, getDelimiter());
     }
 
     @Override

Modified: james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java (original)
+++ james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/JCRMessageManager.java Wed May 25 17:33:30 2011
@@ -31,7 +31,6 @@ import org.apache.james.mailbox.jcr.mail
 import org.apache.james.mailbox.jcr.mail.model.JCRMailbox;
 import org.apache.james.mailbox.jcr.mail.model.JCRMessage;
 import org.apache.james.mailbox.store.StoreMessageManager;
-import org.apache.james.mailbox.store.mail.UidProvider;
 import org.apache.james.mailbox.store.mail.model.Header;
 import org.apache.james.mailbox.store.mail.model.Message;
 import org.apache.james.mailbox.store.mail.model.PropertyBuilder;
@@ -46,9 +45,9 @@ public class JCRMessageManager extends S
 
     private final Logger log;
 
-    public JCRMessageManager(JCRMailboxSessionMapperFactory mapperFactory, final UidProvider<String> uidProvider,
+    public JCRMessageManager(JCRMailboxSessionMapperFactory mapperFactory, 
             final MailboxEventDispatcher dispatcher, final JCRMailbox mailbox, final Logger log, final char delimiter) throws MailboxException {
-        super(mapperFactory, uidProvider, dispatcher, mailbox);
+        super(mapperFactory, dispatcher, mailbox);
         this.log = log;
     }
 
@@ -58,12 +57,12 @@ public class JCRMessageManager extends S
     }
 
     @Override
-    protected Message<String> createMessage(long uid, Date internalDate, int size, int bodyStartOctet, InputStream document, Flags flags, List<Header> headers, PropertyBuilder propertyBuilder) throws MailboxException{
+    protected Message<String> createMessage(Date internalDate, int size, int bodyStartOctet, InputStream document, Flags flags, List<Header> headers, PropertyBuilder propertyBuilder) throws MailboxException{
         final List<JCRHeader> jcrHeaders = new ArrayList<JCRHeader>(headers.size());
         for (Header header: headers) {
             jcrHeaders.add((JCRHeader) header);
         }
-        final Message<String> message = new JCRMessage(getMailboxEntity().getMailboxId(), uid, internalDate, 
+        final Message<String> message = new JCRMessage(getMailboxEntity().getMailboxId(), internalDate, 
                 size, flags, document, bodyStartOctet, jcrHeaders, propertyBuilder, log);
         return message;
     }

Modified: james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/JCRMessageMapper.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/JCRMessageMapper.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/JCRMessageMapper.java (original)
+++ james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/JCRMessageMapper.java Wed May 25 17:33:30 2011
@@ -23,7 +23,6 @@ import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
@@ -31,10 +30,10 @@ import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
 import javax.jcr.RepositoryException;
+import javax.jcr.Session;
 import javax.jcr.query.Query;
 import javax.jcr.query.QueryManager;
 import javax.jcr.query.QueryResult;
-import javax.mail.Flags;
 
 import org.apache.jackrabbit.commons.JcrUtils;
 import org.apache.jackrabbit.util.ISO9075;
@@ -43,10 +42,10 @@ import org.apache.james.mailbox.MailboxS
 import org.apache.james.mailbox.MessageMetaData;
 import org.apache.james.mailbox.MessageRange;
 import org.apache.james.mailbox.MessageRange.Type;
-import org.apache.james.mailbox.UpdatedFlags;
-import org.apache.james.mailbox.jcr.AbstractJCRMapper;
+import org.apache.james.mailbox.jcr.JCRImapConstants;
 import org.apache.james.mailbox.jcr.MailboxSessionJCRRepository;
 import org.apache.james.mailbox.jcr.mail.model.JCRMessage;
+import org.apache.james.mailbox.store.mail.AbstractMessageMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.mail.SimpleMessageMetaData;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
@@ -58,7 +57,7 @@ import org.slf4j.Logger;
  * a seperate child node under the mailbox
  *
  */
-public class JCRMessageMapper extends AbstractJCRMapper implements MessageMapper<String> {
+public class JCRMessageMapper extends AbstractMessageMapper<String> implements JCRImapConstants {
     
     /**
      * Store the messages directly in the mailbox: .../mailbox/
@@ -96,7 +95,12 @@ public class JCRMessageMapper extends Ab
     public final static int MESSAGE_SCALE_MINUTE = 5;
 
     private final int scaleType;
+    
+    private final Logger logger;
+    private final MailboxSessionJCRRepository repository;
+    protected final MailboxSession mSession;
 
+    
     /**
      * Construct a new {@link JCRMessageMapper} instance
      * 
@@ -104,16 +108,73 @@ public class JCRMessageMapper extends Ab
      * @param session {@link MailboxSession} to which the mapper is bound
      * @param logger Log
      */
-    public JCRMessageMapper(final MailboxSessionJCRRepository repos, MailboxSession session, final Logger logger, int scaleType) {
-        super(repos, session, logger);
+    public JCRMessageMapper(final MailboxSessionJCRRepository repository, MailboxSession mSession, final Logger logger, int scaleType) {
+        this.repository = repository;
+        this.mSession = mSession;
+        this.logger = logger;
         this.scaleType = scaleType;
     }
     
     public JCRMessageMapper(final MailboxSessionJCRRepository repos, MailboxSession session, final Logger logger) {
         this(repos, session, logger, MESSAGE_SCALE_DAY);
     }
+
+    /**
+     * Return the logger
+     * 
+     * @return logger
+     */
+    protected Logger getLogger() {
+        return logger;
+    }
     
     /**
+     * Return the JCR Session
+     * 
+     * @return session
+     */
+    protected Session getSession() throws RepositoryException{
+        return repository.login(mSession);
+    }
+
+    /**
+     * Begin is not supported by level 1 JCR implementations, however we refresh the session
+     */
+    protected void begin() throws MailboxException {  
+        try {
+            getSession().refresh(true);
+        } catch (RepositoryException e) {
+            // do nothin on refresh
+        }
+        // Do nothing
+    }
+
+    /**
+     * Just call save on the underlying JCR Session, because level 1 JCR implementation does not offer Transactions
+     */
+    protected void commit() throws MailboxException {
+        try {
+            if (getSession().hasPendingChanges()) {
+                getSession().save();
+            }
+        } catch (RepositoryException e) {
+            throw new MailboxException("Unable to commit", e);
+        }
+    }
+
+    /**
+     * Rollback is not supported by level 1 JCR implementations, so just do nothing
+     */
+    protected void rollback() throws MailboxException {
+        try {
+            // just refresh session and discard all pending changes
+            getSession().refresh(false);
+        } catch (RepositoryException e) {
+            // just catch on rollback by now
+        }
+    }
+
+    /**
      * Return the path to the mailbox. This path is escaped to be able to use it in xpath queries
      * 
      * See http://wiki.apache.org/jackrabbit/EncodingAndEscaping
@@ -381,7 +442,7 @@ public class JCRMessageMapper extends Ab
      * (non-Javadoc)
      * @see org.apache.james.mailbox.store.mail.MessageMapper#expungeMarkedForDeletionInMailbox(org.apache.james.mailbox.store.mail.model.Mailbox, org.apache.james.mailbox.MessageRange)
      */
-    public Map<Long, MessageMetaData> expungeMarkedForDeletionInMailbox(Mailbox<String> mailbox, MessageRange set) throws MailboxException {
+    public Map<Long, MessageMetaData> expungeMarkedForDeletion(Mailbox<String> mailbox, MessageRange set) throws MailboxException {
         try {
             final List<Message<String>> results;
             final long from = set.getUidFrom();
@@ -473,11 +534,98 @@ public class JCRMessageMapper extends Ab
         }
     }
 
+    /**
+     * Convert the given int value to a String. If the int value is smaller then
+     * 9 it will prefix the String with 0.
+     * 
+     * @param value
+     * @return stringValue
+     */
+    private String convertIntToString(int value) {
+        if (value <= 9) {
+            return "0" + String.valueOf(value);
+        } else {
+            return String.valueOf(value);
+        }
+    }
+
+
+
+   
+
+
+
+    /**
+     * Logout from open JCR Session
+     */
+    public void endRequest() {
+       repository.logout(mSession);
+    }
+    
+
     /*
      * (non-Javadoc)
-     * @see org.apache.james.mailbox.store.mail.MessageMapper#save(org.apache.james.mailbox.store.mail.model.Mailbox, org.apache.james.mailbox.store.mail.model.MailboxMembership)
+     * @see org.apache.james.mailbox.store.mail.AbstractMessageMapper#calculateHigestModSeq(org.apache.james.mailbox.store.mail.model.Mailbox)
      */
-    public long add(Mailbox<String> mailbox, Message<String> message) throws MailboxException {
+    protected long calculateHigestModSeq(Mailbox<String> mailbox) throws MailboxException {
+        try {
+            Session s = getSession();
+            // we use order by because without it count will always be 0 in jackrabbit
+            String queryString = "/jcr:root/" + ISO9075.encodePath(s.getNodeByIdentifier(mailbox.getMailboxId()).getPath()) + "//element(*,jamesMailbox:message) order by @" + JCRMessage.MODSEQ_PROPERTY + " descending";
+            QueryManager manager = s.getWorkspace().getQueryManager();
+            Query q = manager.createQuery(queryString, Query.XPATH);
+            q.setLimit(1);
+            QueryResult result = q.execute();
+            NodeIterator nodes = result.getNodes();
+            if (nodes.hasNext()) {
+                return nodes.nextNode().getProperty(JCRMessage.UID_PROPERTY).getLong();
+            }
+            return 0;
+        } catch (RepositoryException e) {
+            throw new MailboxException("Unable to count unseen messages in mailbox " + mailbox, e);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.mailbox.store.mail.AbstractMessageMapper#calculateLastUid(org.apache.james.mailbox.store.mail.model.Mailbox)
+     */
+    protected long calculateLastUid(Mailbox<String> mailbox) throws MailboxException {
+        try {
+            Session s = getSession();
+            // we use order by because without it count will always be 0 in jackrabbit
+            String queryString = "/jcr:root/" + ISO9075.encodePath(s.getNodeByIdentifier(mailbox.getMailboxId()).getPath()) + "//element(*,jamesMailbox:message) order by @" + JCRMessage.UID_PROPERTY + " descending";
+            QueryManager manager = s.getWorkspace().getQueryManager();
+            Query q = manager.createQuery(queryString, Query.XPATH);
+            q.setLimit(1);
+            QueryResult result = q.execute();
+            NodeIterator nodes = result.getNodes();
+            if (nodes.hasNext()) {
+                return nodes.nextNode().getProperty(JCRMessage.UID_PROPERTY).getLong();
+            }
+            return 0;
+        } catch (RepositoryException e) {
+            throw new MailboxException("Unable to count unseen messages in mailbox " + mailbox, e);
+        }
+    }
+
+    @Override
+    protected void copy(Mailbox<String> mailbox, long uid, long modSeq, Message<String> original) throws MailboxException {
+        try {
+            String newMessagePath = getSession().getNodeByIdentifier(mailbox.getMailboxId()).getPath() + NODE_DELIMITER + String.valueOf(uid);
+            getSession().getWorkspace().copy(((JCRMessage)original).getNode().getPath(), getSession().getNodeByIdentifier(mailbox.getMailboxId()).getPath() + NODE_DELIMITER + String.valueOf(uid));
+            Node node = getSession().getNode(newMessagePath);
+            node.setProperty(JCRMessage.MAILBOX_UUID_PROPERTY, mailbox.getMailboxId());
+            node.setProperty(JCRMessage.UID_PROPERTY, uid);
+            node.setProperty(JCRMessage.MODSEQ_PROPERTY, modSeq);
+
+        } catch (RepositoryException e) {
+            throw new MailboxException("Unable to copy message " +original + " in mailbox " + mailbox, e);
+        }        
+    }
+
+    @Override
+    protected void save(Mailbox<String> mailbox, Message<String> message) throws MailboxException {
         final JCRMessage membership = (JCRMessage) message;
         try {
 
@@ -538,108 +686,18 @@ public class JCRMessageMapper extends Ab
                 messageNode.addMixin("jamesMailbox:message");
                 try {
                     membership.merge(messageNode);
-                    messageNode.setProperty(JCRMessage.UID_PROPERTY, uid);
 
                 } catch (IOException e) {
                     throw new RepositoryException("Unable to merge message in to tree", e);
-                }
-                return uid;
-                
+                }                
             } else {
                 membership.merge(messageNode);
-                return membership.getUid();
             }
         } catch (RepositoryException e) {
             throw new MailboxException("Unable to save message " + message + " in mailbox " + mailbox, e);
         } catch (IOException e) {
             throw new MailboxException("Unable to save message " + message + " in mailbox " + mailbox, e);
-        }
-
-    }
-
-    /**
-     * Convert the given int value to a String. If the int value is smaller then
-     * 9 it will prefix the String with 0.
-     * 
-     * @param value
-     * @return stringValue
-     */
-    private String convertIntToString(int value) {
-        if (value <= 9) {
-            return "0" + String.valueOf(value);
-        } else {
-            return String.valueOf(value);
-        }
-    }
-
-
-
-    /*
-     * (non-Javadoc)
-     * @see org.apache.james.mailbox.store.mail.MessageMapper#copy(org.apache.james.mailbox.store.mail.model.Mailbox, long, org.apache.james.mailbox.store.mail.model.MailboxMembership)
-     */
-    public long copy(Mailbox<String> mailbox, long uid, Message<String> oldmessage) throws MailboxException{
-        try {
-            String newMessagePath = getSession().getNodeByIdentifier(mailbox.getMailboxId()).getPath() + NODE_DELIMITER + String.valueOf(uid);
-            getSession().getWorkspace().copy(((JCRMessage)oldmessage).getNode().getPath(), getSession().getNodeByIdentifier(mailbox.getMailboxId()).getPath() + NODE_DELIMITER + String.valueOf(uid));
-            Node node = getSession().getNode(newMessagePath);
-            node.setProperty(JCRMessage.MAILBOX_UUID_PROPERTY, mailbox.getMailboxId());
-            node.setProperty(JCRMessage.UID_PROPERTY, uid);
-            return uid;
-        } catch (RepositoryException e) {
-            throw new MailboxException("Unable to copy message " +oldmessage + " in mailbox " + mailbox, e);
-        }
+        }        
     }
-    
-   
-    /*
-     * (non-Javadoc)
-     * @see org.apache.james.mailbox.store.mail.MessageMapper#updateFlags(org.apache.james.mailbox.store.mail.model.Mailbox, javax.mail.Flags, boolean, boolean, org.apache.james.mailbox.MessageRange)
-     */
-    public Iterator<UpdatedFlags> updateFlags(final Mailbox<String> mailbox, final Flags flags, final boolean value, final boolean replace, MessageRange set) throws MailboxException {
-        final List<UpdatedFlags> updatedFlags = new ArrayList<UpdatedFlags>();
 
-        findInMailbox(mailbox, set, new MailboxMembershipCallback<String>() {
-			
-			public void onMailboxMembers(List<Message<String>> members)
-					throws MailboxException {
-
-				for (final Message<String> member:members) {
-		            Flags originalFlags = member.createFlags();
-		            if (replace) {
-		                member.setFlags(flags);
-		            } else {
-		                Flags current = member.createFlags();
-		                if (value) {
-		                    current.add(flags);
-		                } else {
-		                    current.remove(flags);
-		                }
-		                member.setFlags(current);
-		            }
-		            Flags newFlags = member.createFlags();
-		            
-		            JCRMessage membership = (JCRMessage) member;
-		            if (membership.isPersistent()) {
-		                try {
-		                    Node messageNode = getSession().getNodeByIdentifier(membership.getId());
-		                    membership.merge(messageNode);
-		                } catch (RepositoryException e) {
-		                    throw new MailboxException("Unable to update flags for message " + membership + " in mailbox " + mailbox, e);
-
-		                } catch (IOException e) {
-		                    throw new MailboxException("Unable to update flags for message " + membership + " in mailbox " + mailbox, e);
-
-		                }
-		            }
-		            
-		            updatedFlags.add(new UpdatedFlags(member.getUid(),originalFlags, newFlags));
-		        }
-
-				
-			}
-		});
-        
-        return updatedFlags.iterator();       
-    }
 }

Modified: james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/model/JCRMessage.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/model/JCRMessage.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/model/JCRMessage.java (original)
+++ james/mailbox/trunk/jcr/src/main/java/org/apache/james/mailbox/jcr/mail/model/JCRMessage.java Wed May 25 17:33:30 2011
@@ -73,6 +73,7 @@ public class JCRMessage extends Abstract
     private boolean recent;
     private boolean seen;
     private String[] userFlags;
+    private long modSeq;
     
     private static final String TOSTRING_SEPARATOR = " ";
 
@@ -95,13 +96,14 @@ public class JCRMessage extends Abstract
     public final static String PROPERTY_NODE_TYPE =  "jamesMailbox:messageProperty";
     public final static String TEXTUAL_LINE_COUNT_PROPERTY  = "jamesMailbox:messageTextualLineCount";
     public final static String SUBTYPE_PROPERTY  = "jamesMailbox:messageSubType";
+    public final static String MODSEQ_PROPERTY = "jamesMailbox:modSeq";
 
     public JCRMessage(Node node, Logger logger) {
         this.logger= logger;
         this.node = node;
     }
     
-    public JCRMessage(String mailboxUUID, long uid, Date internalDate, int size, Flags flags, InputStream content,
+    public JCRMessage(String mailboxUUID, Date internalDate, int size, Flags flags, InputStream content,
             int bodyStartOctet, final List<JCRHeader> headers,
             final PropertyBuilder propertyBuilder, Logger logger) {
         super();
@@ -110,7 +112,6 @@ public class JCRMessage extends Abstract
         this.size = size;
         this.logger = logger;
         setFlags(flags);
-        this.uid = uid;
         this.content = content;
        
         this.bodyStartOctet = bodyStartOctet;
@@ -134,13 +135,13 @@ public class JCRMessage extends Abstract
      * @param message
      * @throws IOException 
      */
-    public JCRMessage(String mailboxUUID, long uid,  JCRMessage message, Logger logger) throws MailboxException {
+    public JCRMessage(String mailboxUUID, long uid,  long modSeq, JCRMessage message, Logger logger) throws MailboxException {
         this.mailboxUUID = mailboxUUID;
         this.internalDate = message.getInternalDate();
         this.size = message.getFullContentOctets();
         setFlags(message.createFlags());
         this.uid = uid;
-        
+        this.modSeq = modSeq;
         this.logger = logger;
         try {
             this.content = new ByteArrayInputStream(IOUtils.toByteArray(message.getFullContent()));
@@ -325,6 +326,8 @@ public class JCRMessage extends Abstract
             node.setProperty(SIZE_PROPERTY, getFullContentOctets());
             node.setProperty(MAILBOX_UUID_PROPERTY, getMailboxId());
             node.setProperty(UID_PROPERTY, getUid());
+            node.setProperty(MODSEQ_PROPERTY, getModSeq());
+
             if (getInternalDate() == null) {
                 internalDate = new Date();
             }
@@ -748,4 +751,53 @@ public class JCRMessage extends Abstract
     public InputStream getBodyContent() throws IOException {
         return new LazySkippingInputStream(getFullContent(), getBodyStartOctet());
     }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.mailbox.store.mail.model.Message#getModSeq()
+     */
+    public long getModSeq() {
+        if (isPersistent()) {
+            try {
+                return node.getProperty(MODSEQ_PROPERTY).getLong();
+
+            } catch (RepositoryException e) {
+                logger.error("Unable to access property " + MODSEQ_PROPERTY, e);
+            }
+            return 0;
+        }
+        return modSeq;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.mailbox.store.mail.model.Message#setModSeq(long)
+     */
+    public void setModSeq(long modSeq) {
+        if (isPersistent()) {
+            try {
+                node.setProperty(MODSEQ_PROPERTY, modSeq);
+            } catch (RepositoryException e) {
+                logger.error("Unable to set mod-sequence", e);
+            }
+        } else {
+            this.modSeq = modSeq;
+        }  
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.mailbox.store.mail.model.Message#setUid(long)
+     */
+    public void setUid(long uid) {
+        if (isPersistent()) {
+            try {
+                node.setProperty(UID_PROPERTY, uid);
+            } catch (RepositoryException e) {
+                logger.error("Unable to set uid", e);
+            }
+        } else {
+            this.uid = uid;
+        }          
+    }
 }

Modified: james/mailbox/trunk/jcr/src/main/resources/org/apache/james/mailbox/jcr/imap.cnd
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jcr/src/main/resources/org/apache/james/mailbox/jcr/imap.cnd?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jcr/src/main/resources/org/apache/james/mailbox/jcr/imap.cnd (original)
+++ james/mailbox/trunk/jcr/src/main/resources/org/apache/james/mailbox/jcr/imap.cnd Wed May 25 17:33:30 2011
@@ -41,6 +41,7 @@
     mixin
     - jamesMailbox:mailboxUUID (String) mandatory
     - jamesMailbox:uid (LONG) mandatory
+    - jamesMailbox:modSeq (LONG)
     - jamesMailbox:size (LONG) mandatory
     - jamesMailbox:answered (BOOLEAN) 
     - jamesMailbox:deleted (BOOLEAN) 

Modified: james/mailbox/trunk/jcr/src/test/java/org/apache/james/mailbox/jcr/JCRMailboxManagerTest.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jcr/src/test/java/org/apache/james/mailbox/jcr/JCRMailboxManagerTest.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jcr/src/test/java/org/apache/james/mailbox/jcr/JCRMailboxManagerTest.java (original)
+++ james/mailbox/trunk/jcr/src/test/java/org/apache/james/mailbox/jcr/JCRMailboxManagerTest.java Wed May 25 17:33:30 2011
@@ -31,7 +31,6 @@ import org.apache.james.mailbox.BadCrede
 import org.apache.james.mailbox.MailboxException;
 import org.apache.james.mailbox.MailboxManagerTest;
 import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.jcr.mail.JCRCachingUidProvider;
 import org.junit.After;
 import org.junit.Before;
 import org.slf4j.LoggerFactory;
@@ -96,10 +95,8 @@ public class JCRMailboxManagerTest exten
         JCRUtils.registerCnd(repository, workspace, user, pass);
         MailboxSessionJCRRepository sessionRepos = new GlobalMailboxSessionJCRRepository(repository, workspace, user, pass);
 
-        JCRCachingUidProvider uidProvider = new JCRCachingUidProvider(sessionRepos);
-
         JCRMailboxSessionMapperFactory mf = new JCRMailboxSessionMapperFactory(sessionRepos);
-        JCRMailboxManager manager = new JCRMailboxManager(mf, null, uidProvider);
+        JCRMailboxManager manager = new JCRMailboxManager(mf, null);
         manager.init();
         setMailboxManager(manager);
     }

Modified: james/mailbox/trunk/jcr/src/test/java/org/apache/james/mailbox/jcr/JCRStressTest.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jcr/src/test/java/org/apache/james/mailbox/jcr/JCRStressTest.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jcr/src/test/java/org/apache/james/mailbox/jcr/JCRStressTest.java (original)
+++ james/mailbox/trunk/jcr/src/test/java/org/apache/james/mailbox/jcr/JCRStressTest.java Wed May 25 17:33:30 2011
@@ -28,7 +28,6 @@ import org.apache.james.mailbox.Abstract
 import org.apache.james.mailbox.MailboxException;
 import org.apache.james.mailbox.MailboxManager;
 import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.jcr.mail.JCRCachingUidProvider;
 import org.junit.After;
 import org.junit.Before;
 import org.slf4j.LoggerFactory;
@@ -55,10 +54,8 @@ public class JCRStressTest extends Abstr
         JCRUtils.registerCnd(repository, workspace, user, pass);
         MailboxSessionJCRRepository sessionRepos = new GlobalMailboxSessionJCRRepository(repository, workspace, user, pass);
 
-        JCRCachingUidProvider uidProvider = new JCRCachingUidProvider(sessionRepos);
-
         JCRMailboxSessionMapperFactory mf = new JCRMailboxSessionMapperFactory(sessionRepos);
-        mailboxManager = new JCRMailboxManager(mf, null, uidProvider);
+        mailboxManager = new JCRMailboxManager(mf, null);
         mailboxManager.init();
 
     }

Modified: james/mailbox/trunk/jpa/pom.xml
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/pom.xml?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jpa/pom.xml (original)
+++ james/mailbox/trunk/jpa/pom.xml Wed May 25 17:33:30 2011
@@ -71,11 +71,7 @@
       <artifactId>h2</artifactId>
       <scope>test</scope>
     </dependency> 
-    <dependency>
-      <groupId>commons-io</groupId>
-      <artifactId>commons-io</artifactId>
-      <scope>test</scope>
-    </dependency>
+
     <dependency>
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>

Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxManager.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxManager.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxManager.java (original)
+++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMailboxManager.java Wed May 25 17:33:30 2011
@@ -26,7 +26,6 @@ import org.apache.james.mailbox.jpa.mail
 import org.apache.james.mailbox.jpa.mail.model.JPAMailbox;
 import org.apache.james.mailbox.store.Authenticator;
 import org.apache.james.mailbox.store.StoreMailboxManager;
-import org.apache.james.mailbox.store.mail.UidProvider;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.transaction.TransactionalMapper;
 
@@ -36,8 +35,8 @@ import org.apache.james.mailbox.store.tr
 public abstract class JPAMailboxManager extends StoreMailboxManager<Long> {
     
     public JPAMailboxManager(JPAMailboxSessionMapperFactory mailboxSessionMapperFactory,
-            final Authenticator authenticator, UidProvider<Long> uidProvider, final MailboxPathLocker locker) {
-        super(mailboxSessionMapperFactory, authenticator, uidProvider, locker);
+            final Authenticator authenticator, final MailboxPathLocker locker) {
+        super(mailboxSessionMapperFactory, authenticator, locker);
     }
     
     @Override

Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java (original)
+++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/JPAMessageManager.java Wed May 25 17:33:30 2011
@@ -31,7 +31,6 @@ import org.apache.james.mailbox.jpa.mail
 import org.apache.james.mailbox.jpa.mail.model.JPAMailbox;
 import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMessage;
 import org.apache.james.mailbox.store.StoreMessageManager;
-import org.apache.james.mailbox.store.mail.UidProvider;
 import org.apache.james.mailbox.store.mail.model.Header;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.Message;
@@ -43,19 +42,18 @@ import org.apache.james.mailbox.util.Mai
  */
 public class JPAMessageManager extends StoreMessageManager<Long> {
     
-    public JPAMessageManager(JPAMailboxSessionMapperFactory mapperFactory, UidProvider<Long> uidProvider,
-            final MailboxEventDispatcher dispatcher,final Mailbox<Long> mailbox) throws MailboxException {
-        super(mapperFactory, uidProvider, dispatcher, mailbox);     
+    public JPAMessageManager(JPAMailboxSessionMapperFactory mapperFactory, final MailboxEventDispatcher dispatcher,final Mailbox<Long> mailbox) throws MailboxException {
+        super(mapperFactory, dispatcher, mailbox);     
     }
     
     @Override
-    protected Message<Long> createMessage(long uid, Date internalDate, final int size, int bodyStartOctet, final InputStream document, 
+    protected Message<Long> createMessage(Date internalDate, final int size, int bodyStartOctet, final InputStream document, 
             final Flags flags, final List<Header> headers, PropertyBuilder propertyBuilder) throws MailboxException{
         final List<JPAHeader> jpaHeaders = new ArrayList<JPAHeader>(headers.size());
         for (Header header: headers) {
             jpaHeaders.add((JPAHeader) header);
         }
-        final Message<Long> message = new JPAMessage((JPAMailbox) getMailboxEntity(), uid, internalDate, size, flags, document, bodyStartOctet, jpaHeaders, propertyBuilder);
+        final Message<Long> message = new JPAMessage((JPAMailbox) getMailboxEntity(), internalDate, size, flags, document, bodyStartOctet, jpaHeaders, propertyBuilder);
         return message;
     }
     

Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java (original)
+++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java Wed May 25 17:33:30 2011
@@ -18,27 +18,26 @@
  ****************************************************************/
 package org.apache.james.mailbox.jpa.mail;
 
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-import javax.mail.Flags;
+import javax.persistence.EntityManager;
 import javax.persistence.EntityManagerFactory;
+import javax.persistence.EntityTransaction;
+import javax.persistence.NoResultException;
 import javax.persistence.PersistenceException;
 import javax.persistence.Query;
 
 import org.apache.james.mailbox.MailboxException;
 import org.apache.james.mailbox.MessageMetaData;
 import org.apache.james.mailbox.MessageRange;
-import org.apache.james.mailbox.UpdatedFlags;
 import org.apache.james.mailbox.MessageRange.Type;
-import org.apache.james.mailbox.jpa.JPATransactionalMapper;
 import org.apache.james.mailbox.jpa.mail.model.JPAMailbox;
 import org.apache.james.mailbox.jpa.mail.model.openjpa.AbstractJPAMessage;
 import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAMessage;
 import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAStreamingMessage;
+import org.apache.james.mailbox.store.mail.AbstractMessageMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper;
 import org.apache.james.mailbox.store.mail.SimpleMessageMetaData;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
@@ -48,12 +47,72 @@ import org.apache.openjpa.persistence.Ar
 /**
  * JPA implementation of a {@link MessageMapper}. This class is not thread-safe!
  */
-public class JPAMessageMapper extends JPATransactionalMapper implements MessageMapper<Long> {
+public class JPAMessageMapper extends AbstractMessageMapper<Long> implements MessageMapper<Long> {
+    protected EntityManagerFactory entityManagerFactory;
+    protected EntityManager entityManager;
     
     public JPAMessageMapper(final EntityManagerFactory entityManagerFactory) {
-        super(entityManagerFactory);
+        this.entityManagerFactory = entityManagerFactory;
     }
 
+
+    /**
+     * Return the currently used {@link EntityManager} or a new one if none exists.
+     * 
+     * @return entitymanger
+     */
+    public EntityManager getEntityManager() {
+        if (entityManager != null)
+            return entityManager;
+        entityManager = entityManagerFactory.createEntityManager();
+        return entityManager;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.mailbox.store.transaction.AbstractTransactionalMapper#begin()
+     */
+    protected void begin() throws MailboxException {
+        try {
+            getEntityManager().getTransaction().begin();
+        } catch (PersistenceException e) {
+            throw new MailboxException("Begin of transaction failed", e);
+        }
+    }
+
+    /**
+     * Commit the Transaction and close the EntityManager
+     */
+    protected void commit() throws MailboxException {
+        try {
+            getEntityManager().getTransaction().commit();
+        } catch (PersistenceException e) {
+            throw new MailboxException("Commit of transaction failed",e);
+        }
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.mailbox.store.transaction.AbstractTransactionalMapper#rollback()
+     */
+    protected void rollback() throws MailboxException {
+        EntityTransaction transaction = entityManager.getTransaction();
+        // check if we have a transaction to rollback
+        if (transaction.isActive()) {
+            getEntityManager().getTransaction().rollback();
+        }
+    }
+
+    /**
+     * Close open {@link EntityManager}
+     */
+    public void endRequest() {
+        if (entityManager != null) {
+            if (entityManager.isOpen())
+                entityManager.close();
+            entityManager = null;
+        }
+    }
     /**
      * @see org.apache.james.mailbox.store.mail.MessageMapper#findInMailbox(org.apache.james.mailbox.MessageRange)
      */
@@ -138,9 +197,9 @@ public class JPAMessageMapper extends JP
 
     /*
      * (non-Javadoc)
-     * @see org.apache.james.mailbox.store.mail.MessageMapper#expungeMarkedForDeletionInMailbox(org.apache.james.mailbox.store.mail.model.Mailbox, org.apache.james.mailbox.MessageRange)
+     * @see org.apache.james.mailbox.store.mail.AbstractMessageMapper#expungeMarkedForDeletion(org.apache.james.mailbox.store.mail.model.Mailbox, org.apache.james.mailbox.MessageRange)
      */
-    public Map<Long, MessageMetaData> expungeMarkedForDeletionInMailbox(Mailbox<Long> mailbox, final MessageRange set) throws MailboxException {
+    public Map<Long, MessageMetaData> expungeMarkedForDeletion(Mailbox<Long> mailbox, final MessageRange set) throws MailboxException {
         try {
             final Map<Long, MessageMetaData> data;
             final List<Message<Long>> results;
@@ -305,76 +364,73 @@ public class JPAMessageMapper extends JP
         }
     }
 
+
+
     /*
      * (non-Javadoc)
-     * @see org.apache.james.mailbox.store.mail.MessageMapper#add(org.apache.james.mailbox.store.mail.model.Mailbox, org.apache.james.mailbox.store.mail.model.MailboxMembership)
+     * @see org.apache.james.mailbox.store.mail.AbstractMessageMapper#calculateHigestModSeq(org.apache.james.mailbox.store.mail.model.Mailbox)
      */
-    public long add(Mailbox<Long> mailbox, Message<Long> message) throws MailboxException {
-
+    protected long calculateHigestModSeq(Mailbox<Long> mailbox) throws MailboxException {
         try {
-            
-            // We need to reload a "JPA attached" mailbox, because the provide mailbox is already "JPA detached"
-            // If we don't this, we will get an org.apache.openjpa.persistence.ArgumentException.
-            ((AbstractJPAMessage) message).setMailbox(getEntityManager().find(JPAMailbox.class, mailbox.getMailboxId()));
-            
-            getEntityManager().persist(message);
-            
-            return message.getUid();
-        
+            final long modSeq = (Long) entityManager.createNamedQuery("findHighestModSeqInMailbox").setParameter("idParam", mailbox.getMailboxId()).setMaxResults(1).getSingleResult();
+            return modSeq;
+        } catch (NoResultException e) {
+            return 0;
         } catch (PersistenceException e) {
-            throw new MailboxException("Save of message " + message + " failed in mailbox " + mailbox, e);
-        } catch (ArgumentException e) {
-            throw new MailboxException("Save of message " + message + " failed in mailbox " + mailbox, e);
+            throw new MailboxException("Unable to retrieve higehst mod-sequence for mailbox " + mailbox);
         }
+    }
 
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.mailbox.store.mail.AbstractMessageMapper#calculateLastUid(org.apache.james.mailbox.store.mail.model.Mailbox)
+     */
+    protected long calculateLastUid(Mailbox<Long> mailbox) throws MailboxException {
+        try {
+            final long uid = (Long) entityManager.createNamedQuery("findLastUidInMailbox").setParameter("idParam", mailbox.getMailboxId()).setMaxResults(1).getSingleResult();
+            return uid;
+        } catch (NoResultException e) {
+            return 0;
+        } catch (PersistenceException e) {
+            throw new MailboxException("Unable to retrieve last uid for mailbox " + mailbox);
+        }
     }
 
+
     /*
      * (non-Javadoc)
-     * @see org.apache.james.mailbox.store.mail.MessageMapper#copy(org.apache.james.mailbox.store.mail.model.Mailbox, long, org.apache.james.mailbox.store.mail.model.MailboxMembership)
+     * @see org.apache.james.mailbox.store.mail.AbstractMessageMapper#copy(org.apache.james.mailbox.store.mail.model.Mailbox, long, long, org.apache.james.mailbox.store.mail.model.Message)
      */
-    public long copy(Mailbox<Long> mailbox, long uid, Message<Long> original) throws MailboxException {
+    protected void copy(Mailbox<Long> mailbox, long uid, long modSeq, Message<Long> original) throws MailboxException {
         Message<Long> copy;
         if (original instanceof JPAStreamingMessage) {
-            copy = new JPAStreamingMessage((JPAMailbox) mailbox, uid, original);
+            copy = new JPAStreamingMessage((JPAMailbox) mailbox, uid, modSeq, original);
         } else {
-            copy = new JPAMessage((JPAMailbox) mailbox, uid,  original);
+            copy = new JPAMessage((JPAMailbox) mailbox, uid, modSeq, original);
         }
-        return add(mailbox, copy);
+        save(mailbox, copy);        
     }
-   
+
+
     /*
      * (non-Javadoc)
-     * @see org.apache.james.mailbox.store.mail.MessageMapper#updateFlags(org.apache.james.mailbox.store.mail.model.Mailbox, javax.mail.Flags, boolean, boolean, org.apache.james.mailbox.MessageRange)
+     * @see org.apache.james.mailbox.store.mail.AbstractMessageMapper#save(org.apache.james.mailbox.store.mail.model.Mailbox, org.apache.james.mailbox.store.mail.model.Message)
      */
-    public Iterator<UpdatedFlags> updateFlags(Mailbox<Long> mailbox, final Flags flags, final boolean value, final boolean replace, MessageRange set) throws MailboxException {
-
-        final List<UpdatedFlags> updatedFlags = new ArrayList<UpdatedFlags>();
-        findInMailbox(mailbox, set, new MailboxMembershipCallback<Long>() {
-
-            public void onMailboxMembers(List<Message<Long>> members) throws MailboxException {
-                for (final Message<Long> member : members) {
-                    Flags originalFlags = member.createFlags();
-                    if (replace) {
-                        member.setFlags(flags);
-                    } else {
-                        Flags current = member.createFlags();
-                        if (value) {
-                            current.add(flags);
-                        } else {
-                            current.remove(flags);
-                        }
-                        member.setFlags(current);
-                    }
-                    Flags newFlags = member.createFlags();
-                    getEntityManager().persist(member);
-                    updatedFlags.add(new UpdatedFlags(member.getUid(), originalFlags, newFlags));
-                }
-
-            }
-        });
-
-        return updatedFlags.iterator();
+    protected void save(Mailbox<Long> mailbox, Message<Long> message) throws MailboxException {
 
+        try {
+            
+            // We need to reload a "JPA attached" mailbox, because the provide mailbox is already "JPA detached"
+            // If we don't this, we will get an org.apache.openjpa.persistence.ArgumentException.
+            ((AbstractJPAMessage) message).setMailbox(getEntityManager().find(JPAMailbox.class, mailbox.getMailboxId()));
+            
+            getEntityManager().persist(message);
+                    
+        } catch (PersistenceException e) {
+            throw new MailboxException("Save of message " + message + " failed in mailbox " + mailbox, e);
+        } catch (ArgumentException e) {
+            throw new MailboxException("Save of message " + message + " failed in mailbox " + mailbox, e);
+        }        
     }
 }

Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMessage.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMessage.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMessage.java (original)
+++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/AbstractJPAMessage.java Wed May 25 17:33:30 2011
@@ -94,12 +94,16 @@ import org.apache.openjpa.persistence.jd
             query="DELETE FROM Message message WHERE message.mailbox.mailboxId = :idParam"),
     @NamedQuery(name="findLastUidInMailbox",
             query="SELECT message.uid FROM Message message WHERE message.mailbox.mailboxId = :idParam ORDER BY message.uid DESC"),
+    @NamedQuery(name="findHighestModSeqInMailbox",
+            query="SELECT message.modSeq FROM Message message WHERE message.mailbox.mailboxId = :idParam ORDER BY message.modSeq DESC"),
     @NamedQuery(name="deleteAllMemberships",
             query="DELETE FROM Message message")
 })
 @MappedSuperclass
 public abstract class AbstractJPAMessage extends AbstractMessage<Long> {
 
+
+
     private static final String TOSTRING_SEPARATOR = " ";
 
     /** Identifies composite key */
@@ -158,6 +162,11 @@ public abstract class AbstractJPAMessage
     @Column(name = "MAIL_UID")
     private long uid;
 
+    /** The value for the modSeq field */
+    @Index
+    @Column(name = "MAIL_MODSEQ")
+    private long modSeq;
+
     /** The value for the internalDate field */
     @Basic(optional = false)
     @Column(name = "MAIL_DATE")
@@ -245,11 +254,10 @@ public abstract class AbstractJPAMessage
     @Deprecated
     public AbstractJPAMessage() {}
 
-    public AbstractJPAMessage(JPAMailbox mailbox, long uid, Date internalDate, Flags flags, final long contentOctets, final int bodyStartOctet, final List<JPAHeader> headers, final PropertyBuilder propertyBuilder) {
+    public AbstractJPAMessage(JPAMailbox mailbox, Date internalDate, Flags flags, final long contentOctets, final int bodyStartOctet, final List<JPAHeader> headers, final PropertyBuilder propertyBuilder) {
         super();
         this.mailbox = mailbox;
         this.internalDate = internalDate;
-        this.uid = uid;
         userFlags = new ArrayList<JPAUserFlag>();
 
         setFlags(flags);        
@@ -276,10 +284,11 @@ public abstract class AbstractJPAMessage
      * @param original message to be copied, not null
      * @throws IOException 
      */
-    public AbstractJPAMessage(JPAMailbox mailbox, long uid, Message<?> original) throws MailboxException {
+    public AbstractJPAMessage(JPAMailbox mailbox, long uid, long modSeq,  Message<?> original) throws MailboxException {
         super();
         this.mailbox = mailbox;
         this.uid = uid;
+        this.modSeq = modSeq;
         userFlags = new ArrayList<JPAUserFlag>();
         setFlags(original.createFlags());
         
@@ -343,6 +352,22 @@ public abstract class AbstractJPAMessage
         return true;
     }
 
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.mailbox.store.mail.model.Message#getModSeq()
+     */
+    public long getModSeq() {
+        return modSeq;
+    }
+
+    /*
+     * (non-Javadoc)
+     * @see org.apache.james.mailbox.store.mail.model.Message#setModSeq(long)
+     */
+    public void setModSeq(long modSeq) {
+        this.modSeq = modSeq;
+    }
+    
     /**
      * Gets the top level MIME content media type.
      * 

Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAMessage.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAMessage.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAMessage.java (original)
+++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAMessage.java Wed May 25 17:33:30 2011
@@ -52,9 +52,9 @@ public class JPAMessage extends Abstract
     @Deprecated
     public JPAMessage() {}
 
-    public JPAMessage(JPAMailbox mailbox, long uid, Date internalDate, int size, Flags flags, 
+    public JPAMessage(JPAMailbox mailbox,Date internalDate, int size, Flags flags, 
             InputStream content, int bodyStartOctet, final List<JPAHeader> headers, final PropertyBuilder propertyBuilder) throws MailboxException {
-        super(mailbox, uid, internalDate, flags, size ,bodyStartOctet,headers,propertyBuilder);
+        super(mailbox, internalDate, flags, size ,bodyStartOctet,headers,propertyBuilder);
         try {
             this.content = IOUtils.toByteArray(content);
         } catch (IOException e) {
@@ -68,8 +68,8 @@ public class JPAMessage extends Abstract
      * @param message
      * @throws MailboxException 
      */
-    public JPAMessage(JPAMailbox mailbox, long uid, Message<?> message) throws MailboxException{
-        super(mailbox, uid, message);
+    public JPAMessage(JPAMailbox mailbox, long uid, long modSeq, Message<?> message) throws MailboxException{
+        super(mailbox, uid, modSeq, message);
         try {
             this.content = IOUtils.toByteArray(message.getFullContent());
         } catch (IOException e) {

Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAStreamingMessage.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAStreamingMessage.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAStreamingMessage.java (original)
+++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/model/openjpa/JPAStreamingMessage.java Wed May 25 17:33:30 2011
@@ -61,9 +61,9 @@ public class JPAStreamingMessage extends
     @Deprecated
     public JPAStreamingMessage() {}
 
-    public JPAStreamingMessage(JPAMailbox mailbox, long uid, Date internalDate, int size, Flags flags, 
+    public JPAStreamingMessage(JPAMailbox mailbox, Date internalDate, int size, Flags flags, 
             InputStream content, int bodyStartOctet, final List<JPAHeader> headers, final PropertyBuilder propertyBuilder) throws MailboxException {
-        super(mailbox, uid, internalDate, flags, size ,bodyStartOctet,headers,propertyBuilder);
+        super(mailbox, internalDate, flags, size ,bodyStartOctet,headers,propertyBuilder);
         this.content = content;
     }
 
@@ -73,8 +73,8 @@ public class JPAStreamingMessage extends
      * @param message
      * @throws IOException 
      */
-    public JPAStreamingMessage(JPAMailbox mailbox, long uid,Message<?> message) throws MailboxException {
-        super(mailbox, uid, message);
+    public JPAStreamingMessage(JPAMailbox mailbox, long uid, long modSeq, Message<?> message) throws MailboxException {
+        super(mailbox, uid, modSeq, message);
         try {
             this.content = new ByteArrayInputStream(IOUtils.toByteArray(message.getFullContent()));
         } catch (IOException e) {

Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMailboxManager.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMailboxManager.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMailboxManager.java (original)
+++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMailboxManager.java Wed May 25 17:33:30 2011
@@ -28,7 +28,6 @@ import org.apache.james.mailbox.jpa.JPAM
 import org.apache.james.mailbox.store.Authenticator;
 import org.apache.james.mailbox.store.JVMMailboxPathLocker;
 import org.apache.james.mailbox.store.StoreMessageManager;
-import org.apache.james.mailbox.store.mail.UidProvider;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.util.MailboxEventDispatcher;
 
@@ -40,18 +39,18 @@ public class OpenJPAMailboxManager exten
 
     private boolean useStreaming;
 
-    public OpenJPAMailboxManager(JPAMailboxSessionMapperFactory mapperFactory, Authenticator authenticator, UidProvider<Long> uidProvider, MailboxPathLocker locker, boolean useStreaming) {
-        super(mapperFactory, authenticator, uidProvider, locker);
+    public OpenJPAMailboxManager(JPAMailboxSessionMapperFactory mapperFactory, Authenticator authenticator, MailboxPathLocker locker, boolean useStreaming) {
+        super(mapperFactory, authenticator,  locker);
         this.useStreaming = useStreaming;
     }
 
-    public OpenJPAMailboxManager(JPAMailboxSessionMapperFactory mapperFactory, Authenticator authenticator, UidProvider<Long> uidProvider) {
-        this(mapperFactory, authenticator, uidProvider, new JVMMailboxPathLocker(), false);
+    public OpenJPAMailboxManager(JPAMailboxSessionMapperFactory mapperFactory, Authenticator authenticator) {
+        this(mapperFactory, authenticator, new JVMMailboxPathLocker(), false);
     }
 
     @Override
-    protected StoreMessageManager<Long> createMessageManager(UidProvider<Long> uidProvider, MailboxEventDispatcher dispatcher, Mailbox<Long> mailboxRow, MailboxSession session) throws MailboxException {
-        StoreMessageManager<Long> result =  new OpenJPAMessageManager((JPAMailboxSessionMapperFactory) mailboxSessionMapperFactory, uidProvider, dispatcher, mailboxRow, useStreaming);
+    protected StoreMessageManager<Long> createMessageManager(MailboxEventDispatcher dispatcher, Mailbox<Long> mailboxRow, MailboxSession session) throws MailboxException {
+        StoreMessageManager<Long> result =  new OpenJPAMessageManager((JPAMailboxSessionMapperFactory) mailboxSessionMapperFactory, dispatcher, mailboxRow, useStreaming);
         return result;
     }
 }

Modified: james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java (original)
+++ james/mailbox/trunk/jpa/src/main/java/org/apache/james/mailbox/jpa/openjpa/OpenJPAMessageManager.java Wed May 25 17:33:30 2011
@@ -32,7 +32,6 @@ import org.apache.james.mailbox.jpa.JPAM
 import org.apache.james.mailbox.jpa.mail.model.JPAHeader;
 import org.apache.james.mailbox.jpa.mail.model.JPAMailbox;
 import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAStreamingMessage;
-import org.apache.james.mailbox.store.mail.UidProvider;
 import org.apache.james.mailbox.store.mail.model.Header;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.Message;
@@ -46,27 +45,27 @@ public class OpenJPAMessageManager exten
 
     private final boolean useStreaming;
 
-    public OpenJPAMessageManager(JPAMailboxSessionMapperFactory mapperFactory, UidProvider<Long> uidProvider,
+    public OpenJPAMessageManager(JPAMailboxSessionMapperFactory mapperFactory,
             MailboxEventDispatcher dispatcher, Mailbox<Long> mailbox) throws MailboxException {
-        this(mapperFactory, uidProvider, dispatcher, mailbox, false);
+        this(mapperFactory, dispatcher, mailbox, false);
     }
 
-    public OpenJPAMessageManager(JPAMailboxSessionMapperFactory mapperFactory, UidProvider<Long> uidProvider,
+    public OpenJPAMessageManager(JPAMailboxSessionMapperFactory mapperFactory,
             MailboxEventDispatcher dispatcher, Mailbox<Long> mailbox, final boolean useStreaming) throws MailboxException {
-        super(mapperFactory, uidProvider, dispatcher, mailbox);
+        super(mapperFactory,  dispatcher, mailbox);
         this.useStreaming = useStreaming;
     }
 
     @Override
-    protected Message<Long> createMessage(long uid, Date internalDate, int size, int bodyStartOctet, InputStream document, Flags flags, List<Header> headers, PropertyBuilder propertyBuilder) throws MailboxException {
+    protected Message<Long> createMessage(Date internalDate, int size, int bodyStartOctet, InputStream document, Flags flags, List<Header> headers, PropertyBuilder propertyBuilder) throws MailboxException {
         if (useStreaming) {
             final List<JPAHeader> jpaHeaders = new ArrayList<JPAHeader>(headers.size());
             for (Header header: headers) {
                 jpaHeaders.add((JPAHeader) header);
             }
-            return new JPAStreamingMessage((JPAMailbox) getMailboxEntity(), uid, internalDate, size, flags, document, bodyStartOctet, jpaHeaders, propertyBuilder);
+            return new JPAStreamingMessage((JPAMailbox) getMailboxEntity(), internalDate, size, flags, document, bodyStartOctet, jpaHeaders, propertyBuilder);
         } else {
-            return super.createMessage(uid, internalDate, size, bodyStartOctet, document, flags, headers, propertyBuilder);
+            return super.createMessage(internalDate, size, bodyStartOctet, document, flags, headers, propertyBuilder);
         }
     }
 

Modified: james/mailbox/trunk/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java
URL: http://svn.apache.org/viewvc/james/mailbox/trunk/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java?rev=1127594&r1=1127593&r2=1127594&view=diff
==============================================================================
--- james/mailbox/trunk/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java (original)
+++ james/mailbox/trunk/jpa/src/test/java/org/apache/james/mailbox/jpa/JPAMailboxManagerTest.java Wed May 25 17:33:30 2011
@@ -26,7 +26,6 @@ import org.apache.james.mailbox.BadCrede
 import org.apache.james.mailbox.MailboxException;
 import org.apache.james.mailbox.MailboxManagerTest;
 import org.apache.james.mailbox.MailboxSession;
-import org.apache.james.mailbox.jpa.mail.JPACachingUidProvider;
 import org.apache.james.mailbox.jpa.mail.model.JPAHeader;
 import org.apache.james.mailbox.jpa.mail.model.JPAMailbox;
 import org.apache.james.mailbox.jpa.mail.model.JPAProperty;
@@ -96,10 +95,9 @@ public class JPAMailboxManagerTest exten
                 JPASubscription.class.getName() + ")");
        
         entityManagerFactory = OpenJPAPersistence.getEntityManagerFactory(properties);
-        JPACachingUidProvider uidProvider = new JPACachingUidProvider(entityManagerFactory);
         JPAMailboxSessionMapperFactory mf = new JPAMailboxSessionMapperFactory(entityManagerFactory);
 
-        JPAMailboxManager mailboxManager = new OpenJPAMailboxManager(mf, null, uidProvider);
+        JPAMailboxManager mailboxManager = new OpenJPAMailboxManager(mf, null);
         mailboxManager.init();
 
         setMailboxManager(mailboxManager);



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org