001/**************************************************************** 002 * Licensed to the Apache Software Foundation (ASF) under one * 003 * or more contributor license agreements. See the NOTICE file * 004 * distributed with this work for additional information * 005 * regarding copyright ownership. The ASF licenses this file * 006 * to you under the Apache License, Version 2.0 (the * 007 * "License"); you may not use this file except in compliance * 008 * with the License. You may obtain a copy of the License at * 009 * * 010 * http://www.apache.org/licenses/LICENSE-2.0 * 011 * * 012 * Unless required by applicable law or agreed to in writing, * 013 * software distributed under the License is distributed on an * 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * 015 * KIND, either express or implied. See the License for the * 016 * specific language governing permissions and limitations * 017 * under the License. * 018 ****************************************************************/ 019 020package org.apache.james.mailbox.jpa.mail; 021 022import java.util.List; 023 024import javax.persistence.EntityExistsException; 025import javax.persistence.EntityManagerFactory; 026import javax.persistence.NoResultException; 027import javax.persistence.PersistenceException; 028import javax.persistence.RollbackException; 029 030import org.apache.james.mailbox.exception.MailboxException; 031import org.apache.james.mailbox.exception.MailboxExistsException; 032import org.apache.james.mailbox.exception.MailboxNotFoundException; 033import org.apache.james.mailbox.jpa.JPATransactionalMapper; 034import org.apache.james.mailbox.jpa.mail.model.JPAMailbox; 035import org.apache.james.mailbox.model.MailboxPath; 036import org.apache.james.mailbox.store.mail.MailboxMapper; 037import org.apache.james.mailbox.store.mail.model.Mailbox; 038 039/** 040 * Data access management for mailbox. 041 */ 042public class JPAMailboxMapper extends JPATransactionalMapper implements MailboxMapper<Long> { 043 044 private static final char SQL_WILDCARD_CHAR = '%'; 045 private String lastMailboxName; 046 047 public JPAMailboxMapper(EntityManagerFactory entityManagerFactory) { 048 super(entityManagerFactory); 049 } 050 051 /** 052 * Commit the transaction. If the commit fails due a conflict in a unique key constraint a {@link MailboxExistsException} 053 * will get thrown 054 */ 055 @Override 056 protected void commit() throws MailboxException { 057 try { 058 getEntityManager().getTransaction().commit(); 059 } catch (PersistenceException e) { 060 if (e instanceof EntityExistsException) 061 throw new MailboxExistsException(lastMailboxName); 062 if (e instanceof RollbackException) { 063 Throwable t = e.getCause(); 064 if (t != null && t instanceof EntityExistsException) 065 throw new MailboxExistsException(lastMailboxName); 066 } 067 throw new MailboxException("Commit of transaction failed", e); 068 } 069 } 070 071 /** 072 * @see org.apache.james.mailbox.store.mail.MailboxMapper#save(Mailbox) 073 */ 074 public void save(Mailbox<Long> mailbox) throws MailboxException { 075 try { 076 this.lastMailboxName = mailbox.getName(); 077 getEntityManager().persist(mailbox); 078 } catch (PersistenceException e) { 079 throw new MailboxException("Save of mailbox " + mailbox.getName() +" failed", e); 080 } 081 } 082 083 /** 084 * @see org.apache.james.mailbox.store.mail.MailboxMapper#findMailboxByPath(MailboxPath) 085 */ 086 public Mailbox<Long> findMailboxByPath(MailboxPath mailboxPath) throws MailboxException, MailboxNotFoundException { 087 try { 088 if (mailboxPath.getUser() == null) { 089 return (JPAMailbox) getEntityManager().createNamedQuery("findMailboxByName").setParameter("nameParam", mailboxPath.getName()).setParameter("namespaceParam", mailboxPath.getNamespace()).getSingleResult(); 090 } else { 091 return (JPAMailbox) getEntityManager().createNamedQuery("findMailboxByNameWithUser").setParameter("nameParam", mailboxPath.getName()).setParameter("namespaceParam", mailboxPath.getNamespace()).setParameter("userParam", mailboxPath.getUser()).getSingleResult(); 092 } 093 } catch (NoResultException e) { 094 throw new MailboxNotFoundException(mailboxPath); 095 } catch (PersistenceException e) { 096 throw new MailboxException("Search of mailbox " + mailboxPath + " failed", e); 097 } 098 } 099 100 /** 101 * @see org.apache.james.mailbox.store.mail.MailboxMapper#delete(Mailbox) 102 */ 103 public void delete(Mailbox<Long> mailbox) throws MailboxException { 104 try { 105 getEntityManager().createNamedQuery("deleteMessages").setParameter("idParam", mailbox.getMailboxId()).executeUpdate(); 106 getEntityManager().remove(mailbox); 107 } catch (PersistenceException e) { 108 throw new MailboxException("Delete of mailbox " + mailbox + " failed", e); 109 } 110 } 111 112 /** 113 * @see org.apache.james.mailbox.store.mail.MailboxMapper#findMailboxWithPathLike(MailboxPath) 114 */ 115 @SuppressWarnings("unchecked") 116 public List<Mailbox<Long>> findMailboxWithPathLike(MailboxPath path) throws MailboxException { 117 try { 118 if (path.getUser() == null) { 119 return getEntityManager().createNamedQuery("findMailboxWithNameLike").setParameter("nameParam", SQL_WILDCARD_CHAR + path.getName() + SQL_WILDCARD_CHAR).setParameter("namespaceParam", path.getNamespace()).getResultList(); 120 } else { 121 return getEntityManager().createNamedQuery("findMailboxWithNameLikeWithUser").setParameter("nameParam", SQL_WILDCARD_CHAR + path.getName() + SQL_WILDCARD_CHAR).setParameter("namespaceParam", path.getNamespace()).setParameter("userParam", path.getUser()).getResultList(); 122 } 123 } catch (PersistenceException e) { 124 throw new MailboxException("Search of mailbox " + path + " failed", e); 125 } 126 } 127 128 public void deleteAllMemberships() throws MailboxException { 129 try { 130 getEntityManager().createNamedQuery("deleteAllMemberships").executeUpdate(); 131 } catch (PersistenceException e) { 132 throw new MailboxException("Delete of mailboxes failed", e); 133 } 134 } 135 136 public void deleteAllMailboxes() throws MailboxException { 137 try { 138 getEntityManager().createNamedQuery("deleteAllMailboxes").executeUpdate(); 139 } catch (PersistenceException e) { 140 throw new MailboxException("Delete of mailboxes failed", e); 141 } 142 } 143 144 /** 145 * @see org.apache.james.mailbox.store.mail.MailboxMapper#hasChildren(Mailbox, char) 146 */ 147 public boolean hasChildren(Mailbox<Long> mailbox, char delimiter) throws MailboxException, 148 MailboxNotFoundException { 149 final String name = mailbox.getName() + delimiter + SQL_WILDCARD_CHAR; 150 final Long numberOfChildMailboxes; 151 if (mailbox.getUser() == null) { 152 numberOfChildMailboxes = (Long) getEntityManager().createNamedQuery("countMailboxesWithNameLike").setParameter("nameParam", name).setParameter("namespaceParam", mailbox.getNamespace()).getSingleResult(); 153 } else { 154 numberOfChildMailboxes = (Long) getEntityManager().createNamedQuery("countMailboxesWithNameLikeWithUser").setParameter("nameParam", name).setParameter("namespaceParam", mailbox.getNamespace()).setParameter("userParam", mailbox.getUser()).getSingleResult(); 155 } 156 return numberOfChildMailboxes != null && numberOfChildMailboxes > 0; 157 } 158 159 /** 160 * @see org.apache.james.mailbox.store.mail.MailboxMapper#list() 161 */ 162 @SuppressWarnings("unchecked") 163 public List<Mailbox<Long>> list() throws MailboxException{ 164 try { 165 return getEntityManager().createNamedQuery("listMailboxes").getResultList(); 166 } catch (PersistenceException e) { 167 throw new MailboxException("Delete of mailboxes failed", e); 168 } 169 } 170}