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 package org.apache.james.domainlist.jpa;
020
021 import java.util.ArrayList;
022 import java.util.List;
023
024 import javax.annotation.PostConstruct;
025 import javax.persistence.EntityManager;
026 import javax.persistence.EntityManagerFactory;
027 import javax.persistence.EntityTransaction;
028 import javax.persistence.NoResultException;
029 import javax.persistence.PersistenceException;
030 import javax.persistence.PersistenceUnit;
031
032 import org.apache.james.domainlist.api.DomainListException;
033 import org.apache.james.domainlist.jpa.model.JPADomain;
034 import org.apache.james.domainlist.lib.AbstractDomainList;
035
036 /**
037 * JPA implementation of the DomainList.<br>
038 * This implementation is compatible with the JDBCDomainList, meaning same
039 * database schema can be reused.
040 */
041 public class JPADomainList extends AbstractDomainList {
042
043 /**
044 * The entity manager to access the database.
045 */
046 private EntityManagerFactory entityManagerFactory;
047
048 /**
049 * Set the entity manager to use.
050 *
051 * @param entityManagerFactory
052 */
053 @PersistenceUnit
054 public void setEntityManagerFactory(EntityManagerFactory entityManagerFactory) {
055 this.entityManagerFactory = entityManagerFactory;
056 }
057
058 @PostConstruct
059 public void init() {
060 createEntityManager().close();
061 }
062
063 /**
064 * @see
065 * org.apache.james.domainlist.lib.AbstractDomainList#getDomainListInternal()
066 */
067 @SuppressWarnings("unchecked")
068 protected List<String> getDomainListInternal() throws DomainListException {
069 List<String> domains = new ArrayList<String>();
070 EntityManager entityManager = entityManagerFactory.createEntityManager();
071 final EntityTransaction transaction = entityManager.getTransaction();
072 try {
073 transaction.begin();
074 domains = entityManager.createNamedQuery("listDomainNames").getResultList();
075 transaction.commit();
076 } catch (PersistenceException e) {
077 getLogger().error("Failed to list domains", e);
078 if (transaction.isActive()) {
079 transaction.rollback();
080 }
081 throw new DomainListException("Unable to retrieve domains", e);
082 } finally {
083 entityManager.close();
084 }
085 if (domains.size() == 0) {
086 return null;
087 } else {
088 return new ArrayList<String>(domains);
089 }
090 }
091
092 /**
093 * @see org.apache.james.domainlist.api.DomainList#containsDomain(java.lang.String)
094 */
095 public boolean containsDomain(String domain) throws DomainListException {
096 EntityManager entityManager = entityManagerFactory.createEntityManager();
097 final EntityTransaction transaction = entityManager.getTransaction();
098 try {
099 transaction.begin();
100 JPADomain jpaDomain = (JPADomain) entityManager.createNamedQuery("findDomainByName").setParameter("name", domain).getSingleResult();
101 transaction.commit();
102 return (jpaDomain != null) ? true : false;
103 } catch (NoResultException e) {
104 getLogger().debug("No domain found", e);
105 transaction.commit();
106 return false;
107 } catch (PersistenceException e) {
108 getLogger().error("Failed to find domain", e);
109 if (transaction.isActive()) {
110 transaction.rollback();
111 }
112 throw new DomainListException("Unable to retrieve domains", e);
113 } finally {
114 entityManager.close();
115 }
116 }
117
118 /**
119 * @see
120 * org.apache.james.domainlist.api.DomainList#addDomain(java.lang.String)
121 */
122 public void addDomain(String domain) throws DomainListException {
123 String lowerCasedDomain = domain.toLowerCase();
124 if (containsDomain(lowerCasedDomain)) {
125 throw new DomainListException(lowerCasedDomain + " already exists.");
126 }
127 EntityManager entityManager = entityManagerFactory.createEntityManager();
128 final EntityTransaction transaction = entityManager.getTransaction();
129 try {
130 transaction.begin();
131 JPADomain jpaDomain = new JPADomain(lowerCasedDomain);
132 entityManager.persist(jpaDomain);
133 transaction.commit();
134 } catch (PersistenceException e) {
135 getLogger().error("Failed to save domain", e);
136 if (transaction.isActive()) {
137 transaction.rollback();
138 }
139 throw new DomainListException("Unable to add domain " + domain, e);
140 } finally {
141 entityManager.close();
142 }
143 }
144
145 /**
146 * @see
147 * org.apache.james.domainlist.api.DomainList#removeDomain(java.lang.String)
148 */
149 public void removeDomain(String domain) throws DomainListException {
150 EntityManager entityManager = entityManagerFactory.createEntityManager();
151 final EntityTransaction transaction = entityManager.getTransaction();
152 try {
153 transaction.begin();
154 entityManager.createNamedQuery("deleteDomainByName").setParameter("name", domain).executeUpdate();
155 transaction.commit();
156 } catch (PersistenceException e) {
157 getLogger().error("Failed to remove domain", e);
158 if (transaction.isActive()) {
159 transaction.rollback();
160 }
161 throw new DomainListException("Unable to remove domain " + domain, e);
162
163 } finally {
164 entityManager.close();
165 }
166 }
167
168 /**
169 * Return a new {@link EntityManager} instance
170 *
171 * @return manager
172 */
173 private EntityManager createEntityManager() {
174 return entityManagerFactory.createEntityManager();
175 }
176
177 }