Package org.apache.james.mailbox.jpa.mail

Source Code of org.apache.james.mailbox.jpa.mail.JPAMessageMapper

/****************************************************************
* 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.jpa.mail;

import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceException;
import javax.persistence.Query;

import org.apache.james.mailbox.MailboxSession;
import org.apache.james.mailbox.exception.MailboxException;
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.JPAEncryptedMessage;
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.model.MessageMetaData;
import org.apache.james.mailbox.model.MessageRange;
import org.apache.james.mailbox.model.MessageRange.Type;
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.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.Message;
import org.apache.openjpa.persistence.ArgumentException;

/**
* JPA implementation of a {@link MessageMapper}. This class is not thread-safe!
*/
public class JPAMessageMapper extends AbstractMessageMapper<Long> implements MessageMapper<Long> {
    protected EntityManagerFactory entityManagerFactory;
    protected EntityManager entityManager;

    public JPAMessageMapper(final MailboxSession session, final UidProvider<Long> uidProvider,
            ModSeqProvider<Long> modSeqProvider, final 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;
    }

    /**
     * @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;
        }
    }

    /**
     * @see org.apache.james.mailbox.store.mail.MessageMapper#findInMailbox(org.apache.james.mailbox.store.mail.model.Mailbox,
     *      org.apache.james.mailbox.model.MessageRange,
     *      org.apache.james.mailbox.store.mail.MessageMapper.FetchType, int)
     */
    public Iterator<Message<Long>> findInMailbox(Mailbox<Long> mailbox, MessageRange set, FetchType fType, int max)
            throws MailboxException {
        try {
            List<Message<Long>> results;
            long from = set.getUidFrom();
            final long to = set.getUidTo();
            final Type type = set.getType();

            switch (type) {
            default:
            case ALL:
                results = findMessagesInMailbox(mailbox, max);
                break;
            case FROM:
                results = findMessagesInMailboxAfterUID(mailbox, from, max);
                break;
            case ONE:
                results = findMessagesInMailboxWithUID(mailbox, from);
                break;
            case RANGE:
                results = findMessagesInMailboxBetweenUIDs(mailbox, from, to, max);
                break;
            }

            return results.iterator();

        } catch (PersistenceException e) {
            throw new MailboxException("Search of MessageRange " + set + " failed in mailbox " + mailbox, e);
        }
    }

    /**
     * @see org.apache.james.mailbox.store.mail.MessageMapper#countMessagesInMailbox(Mailbox)
     */
    public long countMessagesInMailbox(Mailbox<Long> mailbox) throws MailboxException {
        try {
            return (Long) getEntityManager().createNamedQuery("countMessagesInMailbox")
                    .setParameter("idParam", mailbox.getMailboxId()).getSingleResult();
        } catch (PersistenceException e) {
            throw new MailboxException("Count of messages failed in mailbox " + mailbox, e);
        }
    }

    /**
     * @see org.apache.james.mailbox.store.mail.MessageMapper#countUnseenMessagesInMailbox(Mailbox)
     */
    public long countUnseenMessagesInMailbox(Mailbox<Long> mailbox) throws MailboxException {
        try {
            return (Long) getEntityManager().createNamedQuery("countUnseenMessagesInMailbox")
                    .setParameter("idParam", mailbox.getMailboxId()).getSingleResult();
        } catch (PersistenceException e) {
            throw new MailboxException("Count of useen messages failed in mailbox " + mailbox, e);
        }
    }

    /**
     * @see org.apache.james.mailbox.store.mail.MessageMapper#delete(org.apache.james.mailbox.store.mail.model.Mailbox,
     *      org.apache.james.mailbox.store.mail.model.Message)
     */
    public void delete(Mailbox<Long> mailbox, Message<Long> message) throws MailboxException {
        try {
            getEntityManager().remove(message);
        } catch (PersistenceException e) {
            throw new MailboxException("Delete of message " + message + " failed in mailbox " + mailbox, e);
        }
    }

    /**
     * @see org.apache.james.mailbox.store.mail.MessageMapper#findFirstUnseenMessageUid(Mailbox)
     */
    @SuppressWarnings("unchecked")
    public Long findFirstUnseenMessageUid(Mailbox<Long> mailbox) throws MailboxException {
        try {
            Query query = getEntityManager().createNamedQuery("findUnseenMessagesInMailboxOrderByUid").setParameter(
                    "idParam", mailbox.getMailboxId());
            query.setMaxResults(1);
            List<Message<Long>> result = query.getResultList();
            if (result.isEmpty()) {
                return null;
            } else {
                return result.get(0).getUid();
            }
        } catch (PersistenceException e) {
            throw new MailboxException("Search of first unseen message failed in mailbox " + mailbox, e);
        }
    }

    /**
     * @see org.apache.james.mailbox.store.mail.MessageMapper#findRecentMessageUidsInMailbox(Mailbox)
     */
    @SuppressWarnings("unchecked")
    public List<Long> findRecentMessageUidsInMailbox(Mailbox<Long> mailbox) throws MailboxException {
        try {
            Query query = getEntityManager().createNamedQuery("findRecentMessageUidsInMailbox").setParameter("idParam",
                    mailbox.getMailboxId());
            return query.getResultList();
        } catch (PersistenceException e) {
            throw new MailboxException("Search of recent messages failed in mailbox " + mailbox, e);
        }
    }

    @Override
    public Map<Long, MessageMetaData> expungeMarkedForDeletionInMailbox(Mailbox<Long> mailbox, MessageRange set)
            throws MailboxException {
        try {
            final Map<Long, MessageMetaData> data;
            final List<Message<Long>> results;
            final long from = set.getUidFrom();
            final long to = set.getUidTo();

            switch (set.getType()) {
            case ONE:
                results = findDeletedMessagesInMailboxWithUID(mailbox, from);
                data = createMetaData(results);
                deleteDeletedMessagesInMailboxWithUID(mailbox, from);
                break;
            case RANGE:
                results = findDeletedMessagesInMailboxBetweenUIDs(mailbox, from, to);
                data = createMetaData(results);
                deleteDeletedMessagesInMailboxBetweenUIDs(mailbox, from, to);
                break;
            case FROM:
                results = findDeletedMessagesInMailboxAfterUID(mailbox, from);
                data = createMetaData(results);
                deleteDeletedMessagesInMailboxAfterUID(mailbox, from);
                break;
            default:
            case ALL:
                results = findDeletedMessagesInMailbox(mailbox);
                data = createMetaData(results);
                deleteDeletedMessagesInMailbox(mailbox);
                break;
            }

            return data;
        } catch (PersistenceException e) {
            throw new MailboxException("Search of MessageRange " + set + " failed in mailbox " + mailbox, e);
        }
    }

    /**
     * (non-Javadoc)
     *
     * @see org.apache.james.mailbox.store.mail.MessageMapper#move(org.apache.james.mailbox.store.mail.model.Mailbox,
     *      org.apache.james.mailbox.store.mail.model.Message)
     */
    @Override
    public MessageMetaData move(Mailbox<Long> mailbox, Message<Long> original) throws MailboxException {
        throw new UnsupportedOperationException("Not implemented - see https://issues.apache.org/jira/browse/IMAP-370");
    }

    /**
     * @see org.apache.james.mailbox.store.mail.AbstractMessageMapper#copy(Mailbox,
     *      long, long, Message)
     */
    protected MessageMetaData 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, modSeq, original);
        } else if (original instanceof JPAEncryptedMessage) {
            copy = new JPAEncryptedMessage((JPAMailbox) mailbox, uid, modSeq, original);
        } else {
            copy = new JPAMessage((JPAMailbox) mailbox, uid, modSeq, original);
        }
        return save(mailbox, copy);
    }

    /**
     * @see org.apache.james.mailbox.store.mail.AbstractMessageMapper#save(Mailbox,
     *      Message)
     */
    protected MessageMetaData 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);
            return new SimpleMessageMetaData(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);
        }
    }

    @SuppressWarnings("unchecked")
    private List<Message<Long>> findMessagesInMailboxAfterUID(Mailbox<Long> mailbox, long uid, int batchSize) {
        Query query = getEntityManager().createNamedQuery("findMessagesInMailboxAfterUID")
                .setParameter("idParam", mailbox.getMailboxId()).setParameter("uidParam", uid);

        if (batchSize > 0)
            query.setMaxResults(batchSize);

        return query.getResultList();
    }

    @SuppressWarnings("unchecked")
    private List<Message<Long>> findMessagesInMailboxWithUID(Mailbox<Long> mailbox, long uid) {
        return getEntityManager().createNamedQuery("findMessagesInMailboxWithUID")
                .setParameter("idParam", mailbox.getMailboxId()).setParameter("uidParam", uid).setMaxResults(1)
                .getResultList();
    }

    @SuppressWarnings("unchecked")
    private List<Message<Long>> findMessagesInMailboxBetweenUIDs(Mailbox<Long> mailbox, long from, long to,
            int batchSize) {
        Query query = getEntityManager().createNamedQuery("findMessagesInMailboxBetweenUIDs")
                .setParameter("idParam", mailbox.getMailboxId()).setParameter("fromParam", from)
                .setParameter("toParam", to);

        if (batchSize > 0)
            query.setMaxResults(batchSize);

        return query.getResultList();
    }

    @SuppressWarnings("unchecked")
    private List<Message<Long>> findMessagesInMailbox(Mailbox<Long> mailbox, int batchSize) {
        Query query = getEntityManager().createNamedQuery("findMessagesInMailbox").setParameter("idParam",
                mailbox.getMailboxId());
        if (batchSize > 0)
            query.setMaxResults(batchSize);
        return query.getResultList();
    }

    private Map<Long, MessageMetaData> createMetaData(List<Message<Long>> uids) {
        final Map<Long, MessageMetaData> data = new HashMap<Long, MessageMetaData>();
        for (int i = 0; i < uids.size(); i++) {
            Message<Long> m = uids.get(i);
            data.put(m.getUid(), new SimpleMessageMetaData(m));
        }
        return data;
    }

    private int deleteDeletedMessagesInMailbox(Mailbox<Long> mailbox) {
        return getEntityManager().createNamedQuery("deleteDeletedMessagesInMailbox")
                .setParameter("idParam", mailbox.getMailboxId()).executeUpdate();
    }

    private int deleteDeletedMessagesInMailboxAfterUID(Mailbox<Long> mailbox, long uid) {
        return getEntityManager().createNamedQuery("deleteDeletedMessagesInMailboxAfterUID")
                .setParameter("idParam", mailbox.getMailboxId()).setParameter("uidParam", uid).executeUpdate();
    }

    private int deleteDeletedMessagesInMailboxWithUID(Mailbox<Long> mailbox, long uid) {
        return getEntityManager().createNamedQuery("deleteDeletedMessagesInMailboxWithUID")
                .setParameter("idParam", mailbox.getMailboxId()).setParameter("uidParam", uid).executeUpdate();
    }

    private int deleteDeletedMessagesInMailboxBetweenUIDs(Mailbox<Long> mailbox, long from, long to) {
        return getEntityManager().createNamedQuery("deleteDeletedMessagesInMailboxBetweenUIDs")
                .setParameter("idParam", mailbox.getMailboxId()).setParameter("fromParam", from)
                .setParameter("toParam", to).executeUpdate();
    }

    @SuppressWarnings("unchecked")
    private List<Message<Long>> findDeletedMessagesInMailbox(Mailbox<Long> mailbox) {
        return getEntityManager().createNamedQuery("findDeletedMessagesInMailbox")
                .setParameter("idParam", mailbox.getMailboxId()).getResultList();
    }

    @SuppressWarnings("unchecked")
    private List<Message<Long>> findDeletedMessagesInMailboxAfterUID(Mailbox<Long> mailbox, long uid) {
        return getEntityManager().createNamedQuery("findDeletedMessagesInMailboxAfterUID")
                .setParameter("idParam", mailbox.getMailboxId()).setParameter("uidParam", uid).getResultList();
    }

    @SuppressWarnings("unchecked")
    private List<Message<Long>> findDeletedMessagesInMailboxWithUID(Mailbox<Long> mailbox, long uid) {
        return getEntityManager().createNamedQuery("findDeletedMessagesInMailboxWithUID")
                .setParameter("idParam", mailbox.getMailboxId()).setParameter("uidParam", uid).setMaxResults(1)
                .getResultList();
    }

    @SuppressWarnings("unchecked")
    private List<Message<Long>> findDeletedMessagesInMailboxBetweenUIDs(Mailbox<Long> mailbox, long from, long to) {
        return getEntityManager().createNamedQuery("findDeletedMessagesInMailboxBetweenUIDs")
                .setParameter("idParam", mailbox.getMailboxId()).setParameter("fromParam", from)
                .setParameter("toParam", to).getResultList();
    }
}
TOP

Related Classes of org.apache.james.mailbox.jpa.mail.JPAMessageMapper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.