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 ro...@apache.org on 2017/01/09 09:13:31 UTC

[3/6] james-project git commit: MAILBOX-279: JPAMessageMapper will extends JPATransactionalMapper as the standard for all JPA

MAILBOX-279: JPAMessageMapper will extends JPATransactionalMapper as the standard for all JPA


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/a377d438
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/a377d438
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/a377d438

Branch: refs/heads/master
Commit: a377d4386db26b57ae34f9a08d7599a0e85e5584
Parents: d4debb5
Author: Quynh Nguyen <qn...@linagora.com>
Authored: Wed Dec 7 14:11:50 2016 +0700
Committer: Quynh Nguyen <qn...@linagora.com>
Committed: Mon Jan 9 15:11:51 2017 +0700

----------------------------------------------------------------------
 .../mailbox/jpa/mail/JPAMessageMapper.java      | 175 ++++++++++---------
 .../mailbox/store/mail/MessageMetadata.java     |  69 ++++++++
 2 files changed, 165 insertions(+), 79 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/a377d438/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java
----------------------------------------------------------------------
diff --git a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java
index 84c4c22..b7542c6 100644
--- a/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java
+++ b/mailbox/jpa/src/main/java/org/apache/james/mailbox/jpa/mail/JPAMessageMapper.java
@@ -23,9 +23,8 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 
-import javax.persistence.EntityManager;
+import javax.mail.Flags;
 import javax.persistence.EntityManagerFactory;
-import javax.persistence.EntityTransaction;
 import javax.persistence.PersistenceException;
 import javax.persistence.Query;
 
@@ -33,6 +32,7 @@ import org.apache.james.mailbox.MailboxSession;
 import org.apache.james.mailbox.MessageUid;
 import org.apache.james.mailbox.exception.MailboxException;
 import org.apache.james.mailbox.jpa.JPAId;
+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.AbstractJPAMailboxMessage;
 import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAEncryptedMailboxMessage;
@@ -41,85 +41,29 @@ import org.apache.james.mailbox.jpa.mail.model.openjpa.JPAStreamingMailboxMessag
 import org.apache.james.mailbox.model.MessageMetaData;
 import org.apache.james.mailbox.model.MessageRange;
 import org.apache.james.mailbox.model.MessageRange.Type;
+import org.apache.james.mailbox.model.UpdatedFlags;
+import org.apache.james.mailbox.store.FlagsUpdateCalculator;
 import org.apache.james.mailbox.store.SimpleMessageMetaData;
-import org.apache.james.mailbox.store.mail.AbstractMessageMapper;
 import org.apache.james.mailbox.store.mail.MessageMapper;
+import org.apache.james.mailbox.store.mail.MessageMetadata;
 import org.apache.james.mailbox.store.mail.ModSeqProvider;
 import org.apache.james.mailbox.store.mail.UidProvider;
 import org.apache.james.mailbox.store.mail.model.Mailbox;
 import org.apache.james.mailbox.store.mail.model.MailboxMessage;
 import org.apache.openjpa.persistence.ArgumentException;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableList;
 
 /**
  * JPA implementation of a {@link MessageMapper}. This class is not thread-safe!
  */
-public class JPAMessageMapper extends AbstractMessageMapper implements MessageMapper {
-    protected EntityManagerFactory entityManagerFactory;
-    protected EntityManager entityManager;
-
-    public JPAMessageMapper(MailboxSession session, UidProvider uidProvider,
-            ModSeqProvider modSeqProvider, EntityManagerFactory entityManagerFactory) {
-        super(session, uidProvider, modSeqProvider);
-        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;
-    }
+public class JPAMessageMapper extends JPATransactionalMapper implements MessageMapper {
+    private final MessageMetadata messageMetadataMapper;
 
-    /**
-     * @see org.apache.james.mailbox.store.transaction.TransactionalMapper#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);
-        }
-    }
-
-    /**
-     * @see org.apache.james.mailbox.store.transaction.TransactionalMapper#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;
-        }
+    public JPAMessageMapper(MailboxSession mailboxSession, UidProvider uidProvider, ModSeqProvider modSeqProvider, EntityManagerFactory entityManagerFactory) {
+        super(entityManagerFactory);
+        this.messageMetadataMapper = new MessageMetadata(mailboxSession, uidProvider, modSeqProvider);
     }
 
     /**
@@ -127,6 +71,7 @@ public class JPAMessageMapper extends AbstractMessageMapper implements MessageMa
      *      org.apache.james.mailbox.model.MessageRange,
      *      org.apache.james.mailbox.store.mail.MessageMapper.FetchType, int)
      */
+    @Override
     public Iterator<MailboxMessage> findInMailbox(Mailbox mailbox, MessageRange set, FetchType fType, int max)
             throws MailboxException {
         try {
@@ -191,12 +136,22 @@ public class JPAMessageMapper extends AbstractMessageMapper implements MessageMa
      */
     public void delete(Mailbox mailbox, MailboxMessage message) throws MailboxException {
         try {
-            getEntityManager().remove(message);
+            AbstractJPAMailboxMessage jpaMessage = getEntityManager().find(AbstractJPAMailboxMessage.class, buildKey(mailbox, message));
+            getEntityManager().remove(jpaMessage);
+
         } catch (PersistenceException e) {
             throw new MailboxException("Delete of message " + message + " failed in mailbox " + mailbox, e);
         }
     }
 
+    private AbstractJPAMailboxMessage.MailboxIdUidKey buildKey(Mailbox mailbox, MailboxMessage message) {
+        JPAId mailboxId = (JPAId) mailbox.getMailboxId();
+        AbstractJPAMailboxMessage.MailboxIdUidKey key = new AbstractJPAMailboxMessage.MailboxIdUidKey();
+        key.mailbox = mailboxId.getRawId();
+        key.uid = message.getUid().asLong();
+        return key;
+    }
+
     @Override
     @SuppressWarnings("unchecked")
     public MessageUid findFirstUnseenMessageUid(Mailbox mailbox) throws MailboxException {
@@ -262,8 +217,8 @@ public class JPAMessageMapper extends AbstractMessageMapper implements MessageMa
             default:
             case ALL:
                 results = findDeletedMessagesInMailbox(mailboxId);
-                data = createMetaData(results);
                 deleteDeletedMessagesInMailbox(mailboxId);
+                data = createMetaData(results);
                 break;
             }
 
@@ -285,15 +240,71 @@ public class JPAMessageMapper extends AbstractMessageMapper implements MessageMa
     }
 
     @Override
-    protected MessageMetaData copy(Mailbox mailbox, MessageUid uid, long modSeq, MailboxMessage original)
+    public MessageMetaData add(Mailbox mailbox, MailboxMessage message) throws MailboxException {
+        messageMetadataMapper.enrichMessage(mailbox, message);
+
+        return save(mailbox, message);
+    }
+
+    @Override
+    public Iterator<UpdatedFlags> updateFlags(Mailbox mailbox, FlagsUpdateCalculator flagsUpdateCalculator,
+            MessageRange set) throws MailboxException {
+        ImmutableList.Builder<UpdatedFlags> updatedFlags = ImmutableList.builder();
+        Iterator<MailboxMessage> messages = findInMailbox(mailbox, set, FetchType.Metadata, -1);
+        
+        long modSeq = -1;
+        if (messages.hasNext()) {
+            modSeq = messageMetadataMapper.nextModSeq(mailbox);
+        }
+        while(messages.hasNext()) {
+            MailboxMessage member = messages.next();
+            Flags originalFlags = member.createFlags();
+            member.setFlags(flagsUpdateCalculator.buildNewFlags(originalFlags));
+            Flags newFlags = member.createFlags();
+            if (UpdatedFlags.flagsChanged(originalFlags, newFlags)) {
+                member.setModSeq(modSeq);
+                save(mailbox, member);
+            }
+
+            UpdatedFlags uFlags = new UpdatedFlags(member.getUid(), member.getModSeq(), originalFlags, newFlags);
+            
+            updatedFlags.add(uFlags);
+            
+        }
+
+        return updatedFlags.build().iterator();
+    }
+
+    @Override
+    public MessageMetaData copy(Mailbox mailbox, MailboxMessage original) throws MailboxException {
+        return copy(mailbox, messageMetadataMapper.nextUid(mailbox), messageMetadataMapper.nextModSeq(mailbox), original);  
+    }
+
+    @Override
+    public Optional<MessageUid> getLastUid(Mailbox mailbox) throws MailboxException {
+        return messageMetadataMapper.getLastUid(mailbox);
+    }
+
+    @Override
+    public long getHighestModSeq(Mailbox mailbox) throws MailboxException {
+        return messageMetadataMapper.getHighestModSeq(mailbox);
+    }
+
+    private MessageMetaData copy(Mailbox mailbox, MessageUid uid, long modSeq, MailboxMessage original)
             throws MailboxException {
         MailboxMessage copy;
+        JPAMailbox currentMailbox;
+        if (mailbox instanceof JPAMailbox) {
+            currentMailbox = (JPAMailbox) mailbox;
+        } else {
+            currentMailbox = new JPAMailbox(mailbox);
+        }
         if (original instanceof JPAStreamingMailboxMessage) {
-            copy = new JPAStreamingMailboxMessage((JPAMailbox) mailbox, uid, modSeq, original);
+            copy = new JPAStreamingMailboxMessage(currentMailbox, uid, modSeq, original);
         } else if (original instanceof JPAEncryptedMailboxMessage) {
-            copy = new JPAEncryptedMailboxMessage((JPAMailbox) mailbox, uid, modSeq, original);
+            copy = new JPAEncryptedMailboxMessage(currentMailbox, uid, modSeq, original);
         } else {
-            copy = new JPAMailboxMessage((JPAMailbox) mailbox, uid, modSeq, original);
+            copy = new JPAMailboxMessage(currentMailbox, uid, modSeq, original);
         }
         return save(mailbox, copy);
     }
@@ -303,19 +314,25 @@ public class JPAMessageMapper extends AbstractMessageMapper implements MessageMa
      *      MailboxMessage)
      */
     protected MessageMetaData save(Mailbox mailbox, MailboxMessage 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.
             JPAId mailboxId = (JPAId) mailbox.getMailboxId();
-            ((AbstractJPAMailboxMessage) message)
-                    .setMailbox(getEntityManager().find(JPAMailbox.class, mailboxId.getRawId()));
+            JPAMailbox currentMailbox = getEntityManager().find(JPAMailbox.class, mailboxId.getRawId());
+            if (message instanceof AbstractJPAMailboxMessage) {
+                ((AbstractJPAMailboxMessage) message).setMailbox(currentMailbox);
+
+                getEntityManager().persist(message);
+                return new SimpleMessageMetaData(message);
+            } else {
+                JPAMailboxMessage persistData = new JPAMailboxMessage(currentMailbox, message.getUid(), message.getModSeq(), message);
+                persistData.setFlags(new Flags());
+                getEntityManager().persist(persistData);
+                return new SimpleMessageMetaData(persistData);
+            }
 
-            getEntityManager().persist(message);
-            return new SimpleMessageMetaData(message);
         } catch (PersistenceException e) {
             throw new MailboxException("Save of message " + message + " failed in mailbox " + mailbox, e);
         } catch (ArgumentException e) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/a377d438/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MessageMetadata.java
----------------------------------------------------------------------
diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MessageMetadata.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MessageMetadata.java
new file mode 100644
index 0000000..1907cf0
--- /dev/null
+++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/mail/MessageMetadata.java
@@ -0,0 +1,69 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one   *
+ * or more contributor license agreements.  See the NOTICE file *
+ * distributed with this work for additional information        *
+ * regarding copyright ownership.  The ASF licenses this file   *
+ * to you under the Apache License, Version 2.0 (the            *
+ * "License"); you may not use this file except in compliance   *
+ * with the License.  You may obtain a copy of the License at   *
+ *                                                              *
+ *   http://www.apache.org/licenses/LICENSE-2.0                 *
+ *                                                              *
+ * Unless required by applicable law or agreed to in writing,   *
+ * software distributed under the License is distributed on an  *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY       *
+ * KIND, either express or implied.  See the License for the    *
+ * specific language governing permissions and limitations      *
+ * under the License.                                           *
+ ****************************************************************/
+
+package org.apache.james.mailbox.store.mail;
+
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageUid;
+import org.apache.james.mailbox.exception.MailboxException;
+import org.apache.james.mailbox.store.mail.model.Mailbox;
+import org.apache.james.mailbox.store.mail.model.MailboxMessage;
+
+import com.google.common.base.Optional;
+
+public class MessageMetadata {
+    private final MailboxSession mailboxSession;
+    private final UidProvider uidProvider;
+    private final ModSeqProvider modSeqProvider;
+
+    public MessageMetadata(MailboxSession mailboxSession, UidProvider uidProvider, ModSeqProvider modSeqProvider) {
+        this.mailboxSession = mailboxSession;
+        this.uidProvider = uidProvider;
+        this.modSeqProvider = modSeqProvider;
+    }
+    
+    public long getHighestModSeq(Mailbox mailbox) throws MailboxException {
+        return modSeqProvider.highestModSeq(mailboxSession, mailbox);
+    }
+
+    public Optional<MessageUid> getLastUid(Mailbox mailbox) throws MailboxException {
+        return uidProvider.lastUid(mailboxSession, mailbox);
+    }
+    
+
+    public MessageUid nextUid(Mailbox mailbox) throws MailboxException {
+        return uidProvider.nextUid(mailboxSession, mailbox);
+    }
+
+    public long nextModSeq(Mailbox mailbox) throws MailboxException {
+        if (modSeqProvider != null) {
+            return modSeqProvider.nextModSeq(mailboxSession, mailbox);
+        }
+        return -1;
+    }
+
+    public void enrichMessage(Mailbox mailbox, MailboxMessage message) throws MailboxException { 
+        message.setUid(nextUid(mailbox));
+        
+        if (modSeqProvider != null) {
+            message.setModSeq(nextModSeq(mailbox));
+        }
+    }
+
+}


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