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 <qngu...@linagora.com> Authored: Wed Dec 7 14:11:50 2016 +0700 Committer: Quynh Nguyen <qngu...@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-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org