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.rrt.jpa;
020
021 import java.util.Collection;
022 import java.util.HashMap;
023 import java.util.List;
024 import java.util.Map;
025
026 import javax.persistence.EntityManager;
027 import javax.persistence.EntityManagerFactory;
028 import javax.persistence.EntityTransaction;
029 import javax.persistence.PersistenceException;
030 import javax.persistence.PersistenceUnit;
031
032 import org.apache.james.rrt.api.RecipientRewriteTableException;
033 import org.apache.james.rrt.jpa.model.JPARecipientRewrite;
034 import org.apache.james.rrt.lib.AbstractRecipientRewriteTable;
035 import org.apache.james.rrt.lib.RecipientRewriteTableUtil;
036
037 /**
038 * Class responsible to implement the Virtual User Table in database with JPA
039 * access.
040 */
041 public class JPARecipientRewriteTable extends AbstractRecipientRewriteTable {
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 /**
059 * @throws RecipientRewriteTableException
060 * @see org.apache.james.rrt.lib.AbstractRecipientRewriteTable#addMappingInternal(String, String, String)
061 */
062 protected void addMappingInternal(String user, String domain, String mapping) throws RecipientRewriteTableException {
063 String fixedUser = getFixedUser(user);
064 String fixedDomain = getFixedDomain(domain);
065 Collection<String> map = getUserDomainMappings(fixedUser, fixedDomain);
066 if (map != null && map.size() != 0) {
067 map.add(mapping);
068 doUpdateMapping(fixedUser, fixedDomain, RecipientRewriteTableUtil.CollectionToMapping(map));
069 } else {
070 doAddMapping(fixedUser, fixedDomain, mapping);
071 }
072 }
073
074 /**
075 * @throws RecipientRewriteTableException
076 * @see org.apache.james.rrt.lib.AbstractRecipientRewriteTable#mapAddressInternal(java.lang.String,
077 * java.lang.String)
078 */
079 protected String mapAddressInternal(String user, String domain) throws RecipientRewriteTableException {
080 EntityManager entityManager = entityManagerFactory.createEntityManager();
081 final EntityTransaction transaction = entityManager.getTransaction();
082 try {
083 transaction.begin();
084 List<JPARecipientRewrite> virtualUsers = entityManager.createNamedQuery("selectMappings").setParameter("user", user).setParameter("domain", domain).getResultList();
085 transaction.commit();
086 if (virtualUsers.size() > 0) {
087 return virtualUsers.get(0).getTargetAddress();
088 }
089 } catch (PersistenceException e) {
090 getLogger().debug("Failed to find mapping for user=" + user + " and domain=" + domain, e);
091 if (transaction.isActive()) {
092 transaction.rollback();
093 }
094 throw new RecipientRewriteTableException("Error while retrieve mappings", e);
095 } finally {
096 entityManager.close();
097 }
098 return null;
099 }
100
101 /**
102 * @throws RecipientRewriteTableException
103 * @see org.apache.james.rrt.lib.AbstractRecipientRewriteTable#mapAddress(java.lang.String, java.lang.String)
104 */
105 protected Collection<String> getUserDomainMappingsInternal(String user, String domain) throws RecipientRewriteTableException {
106 EntityManager entityManager = entityManagerFactory.createEntityManager();
107 final EntityTransaction transaction = entityManager.getTransaction();
108 try {
109 transaction.begin();
110 List<JPARecipientRewrite> virtualUsers = entityManager.createNamedQuery("selectUserDomainMapping").setParameter("user", user).setParameter("domain", domain).getResultList();
111 transaction.commit();
112 if (virtualUsers.size() > 0) {
113 return RecipientRewriteTableUtil.mappingToCollection(virtualUsers.get(0).getTargetAddress());
114 }
115 } catch (PersistenceException e) {
116 getLogger().debug("Failed to get user domain mappings", e);
117 if (transaction.isActive()) {
118 transaction.rollback();
119 }
120 throw new RecipientRewriteTableException("Error while retrieve mappings", e);
121
122 } finally {
123 entityManager.close();
124 }
125 return null;
126 }
127
128 /**
129 * @throws RecipientRewriteTableException
130 * @see org.apache.james.rrt.lib.AbstractRecipientRewriteTable#getAllMappingsInternal()
131 */
132 protected Map<String, Collection<String>> getAllMappingsInternal() throws RecipientRewriteTableException {
133 EntityManager entityManager = entityManagerFactory.createEntityManager();
134 final EntityTransaction transaction = entityManager.getTransaction();
135 Map<String, Collection<String>> mapping = new HashMap<String, Collection<String>>();
136 try {
137 transaction.begin();
138 List<JPARecipientRewrite> virtualUsers = entityManager.createNamedQuery("selectAllMappings").getResultList();
139 transaction.commit();
140 for (JPARecipientRewrite virtualUser : virtualUsers) {
141 mapping.put(virtualUser.getUser() + "@" + virtualUser.getDomain(), RecipientRewriteTableUtil.mappingToCollection(virtualUser.getTargetAddress()));
142 }
143 if (mapping.size() > 0)
144 return mapping;
145 } catch (PersistenceException e) {
146 getLogger().debug("Failed to get all mappings", e);
147 if (transaction.isActive()) {
148 transaction.rollback();
149 }
150 throw new RecipientRewriteTableException("Error while retrieve mappings", e);
151
152 } finally {
153 entityManager.close();
154 }
155 return null;
156 }
157
158 /**
159 * @throws RecipientRewriteTableException
160 * @see org.apache.james.rrt.lib.AbstractRecipientRewriteTable#removeMappingInternal(String, String, String)
161 */
162 protected void removeMappingInternal(String user, String domain, String mapping) throws RecipientRewriteTableException {
163 String fixedUser = getFixedUser(user);
164 String fixedDomain = getFixedDomain(domain);
165 Collection<String> map = getUserDomainMappings(fixedUser, fixedDomain);
166 if (map != null && map.size() > 1) {
167 map.remove(mapping);
168 doUpdateMapping(fixedUser, fixedDomain, RecipientRewriteTableUtil.CollectionToMapping(map));
169 } else {
170 doRemoveMapping(fixedUser, fixedDomain, mapping);
171 }
172 }
173
174 /**
175 * Update the mapping for the given user and domain
176 *
177 * @param user the user
178 * @param domain the domain
179 * @param mapping the mapping
180 * @return true if update was successfully
181 * @throws RecipientRewriteTableException
182 */
183 private boolean doUpdateMapping(String user, String domain, String mapping) throws RecipientRewriteTableException {
184 EntityManager entityManager = entityManagerFactory.createEntityManager();
185 final EntityTransaction transaction = entityManager.getTransaction();
186 try {
187 transaction.begin();
188 int updated = entityManager.createNamedQuery("updateMapping").setParameter("targetAddress", mapping).setParameter("user", user).setParameter("domain", domain).executeUpdate();
189 transaction.commit();
190 if (updated > 0) {
191 return true;
192 }
193 } catch (PersistenceException e) {
194 getLogger().debug("Failed to update mapping", e);
195 if (transaction.isActive()) {
196 transaction.rollback();
197 }
198 throw new RecipientRewriteTableException("Unable to update mapping", e);
199 } finally {
200 entityManager.close();
201 }
202 return false;
203 }
204
205 /**
206 * Remove a mapping for the given user and domain
207 *
208 * @param user the user
209 * @param domain the domain
210 * @param mapping the mapping
211 * @throws RecipientRewriteTableException
212 */
213 private void doRemoveMapping(String user, String domain, String mapping) throws RecipientRewriteTableException {
214 EntityManager entityManager = entityManagerFactory.createEntityManager();
215 final EntityTransaction transaction = entityManager.getTransaction();
216 try {
217 transaction.begin();
218 int deleted = entityManager.createNamedQuery("deleteMapping").setParameter("user", user).setParameter("domain", domain).setParameter("targetAddress", mapping).executeUpdate();
219 transaction.commit();
220
221 } catch (PersistenceException e) {
222 getLogger().debug("Failed to remove mapping", e);
223 if (transaction.isActive()) {
224 transaction.rollback();
225 }
226 throw new RecipientRewriteTableException("Unable to remove mapping", e);
227
228 } finally {
229 entityManager.close();
230 }
231 }
232
233 /**
234 * Add mapping for given user and domain
235 *
236 * @param user the user
237 * @param domain the domain
238 * @param mapping the mapping
239 * @throws RecipientRewriteTableException
240 */
241 private void doAddMapping(String user, String domain, String mapping) throws RecipientRewriteTableException {
242 EntityManager entityManager = entityManagerFactory.createEntityManager();
243 final EntityTransaction transaction = entityManager.getTransaction();
244 try {
245 transaction.begin();
246 JPARecipientRewrite jpaRecipientRewrite = new JPARecipientRewrite(user, domain, mapping);
247 entityManager.persist(jpaRecipientRewrite);
248 transaction.commit();
249 } catch (PersistenceException e) {
250 getLogger().debug("Failed to save virtual user", e);
251 if (transaction.isActive()) {
252 transaction.rollback();
253 }
254 throw new RecipientRewriteTableException("Unable to add mapping", e);
255 } finally {
256 entityManager.close();
257 }
258 }
259
260 }