/* * $Id: SubEthaEntityManager.java 875 2006-11-13 02:45:41Z lhoriman $ * $Source: /cvsroot/Similarity4/src/java/com/similarity/util/Geometry.java,v $ */ package org.subethamail.core.util; import java.net.URL; import java.util.Date; import java.util.List; import java.util.Map; import java.util.logging.Level; import javax.enterprise.context.Dependent; import javax.inject.Inject; import javax.mail.internet.InternetAddress; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.EntityTransaction; import javax.persistence.FlushModeType; import javax.persistence.LockModeType; import javax.persistence.NoResultException; import javax.persistence.Query; import javax.persistence.TypedQuery; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.metamodel.Metamodel; import lombok.extern.java.Log; import org.subethamail.common.NotFoundException; import org.subethamail.entity.Config; import org.subethamail.entity.EmailAddress; import org.subethamail.entity.Mail; import org.subethamail.entity.MailingList; import org.subethamail.entity.Person; import org.subethamail.entity.Subscription; import org.subethamail.entity.SubscriptionHold; import org.subethamail.entity.i.Validator; /** * The methods we add to a regular entity manager to give ourselves * a "prettier" interface. * * NOTE THE CONVENTION: getXXX methods throw a NotFoundException, * while findXXX methods return null or an empty list. I think * it would make more sense the 'other way but EntityManager * already defines a find() method that returns null. * * @author Jeff Schnitzer * @author Scott Hernandez */ @SubEtha @Dependent @Log public class SubEthaEntityManager implements EntityManager { /** The entity manager to use under the covers */ @Inject private EntityManager base; /** * Similar to find(), but throws a NotFoundException instead of returning null * when the key does not exist. */ public <T> T get(Class<T> entityClass, Object primaryKey) throws NotFoundException { T val = this.find(entityClass, primaryKey); if (val == null) throw new NotFoundException("No such " + entityClass.getName() + primaryKey); else return val; } /** * @return the value of a config entity with the specified id, * or null if there is no entity with that id. This method * does not distinguish between missing entities and actual * null values stored as the config value. The return type * will be the stored type of the value. */ public Object findConfigValue(String id) { Config c = this.find(Config.class, id); if (c == null) return null; else return c.getValue(); } /** * Creates or updates the config entity with the specified value. */ public void setConfigValue(String id, Object value) { Config cfg = this.find(Config.class, id); if (cfg == null) { cfg = new Config(id, value); this.persist(cfg); } else { cfg.setValue(value); } } /** * Deletes a config value if it exists */ public void removeConfigValue(String id) { Config cfg = this.find(Config.class, id); if (cfg != null) this.remove(cfg); } /** * Finds an email address with the specified address. Normalizes * the address properly before querying. */ public EmailAddress getEmailAddress(String email) throws NotFoundException { email = Validator.normalizeEmail(email); return this.get(EmailAddress.class, email); } /** * Finds an email address with the specified address. Normalizes * the address properly before querying. * * @return null if no email address associated with that address */ public EmailAddress findEmailAddress(String email) { email = Validator.normalizeEmail(email); return this.find(EmailAddress.class, email); } /** * Tries to find a mail entity which has the specified message id * in the given mailing list. */ public Mail getMailByMessageId(Long listId, String messageId) throws NotFoundException { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding Mail with Message-ID {0}", messageId); Query q = this.createNamedQuery("MailByMessageId"); q.setParameter("listId", listId); q.setParameter("messageId", messageId); try { return (Mail)q.getSingleResult(); } catch (NoResultException ex) { throw new NotFoundException(ex); } } /** * Tries to find mail entites which are looking for an ancestor * with the specified message id. * * @param listId is the id of a mailing list in whose archives to search. * @param messageId is the Message-ID to search for. * * The return values are not readonly. * Will prefetch the wantedReference collection. */ @SuppressWarnings("unchecked") public List<Mail> findMailWantingParent(Long listId, String messageId) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding mail wanting ancestor with Message-ID {0}", messageId); Query q = this.createNamedQuery("WantsReferenceToMessageId"); q.setParameter("listId", listId); q.setParameter("messageId", messageId); return q.getResultList(); } /** * Gets a mailing list with the specified address. */ public MailingList getMailingList(InternetAddress address) throws NotFoundException { String email = Validator.normalizeEmail(address.getAddress()); if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding MailingList with email {0}", email); Query q = this.createNamedQuery("MailingListByEmail"); q.setParameter("email", email); try { return (MailingList)q.getSingleResult(); } catch (NoResultException ex) { log.log(Level.FINE,"Not found"); throw new NotFoundException(ex); } } /** * Gets a mailing list with the specified url */ public MailingList getMailingList(URL url) throws NotFoundException { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding MailingList with url {0}", url); Query q = this.createNamedQuery("MailingListByUrl"); q.setParameter("url", url.toString()); try { return (MailingList)q.getSingleResult(); } catch (NoResultException ex) { log.log(Level.FINE,"Not found"); throw new NotFoundException(ex); } } /** * Finds all mailing lists * @param skip can be -1 for no skip * @param count can be -1 for no limit */ @SuppressWarnings("unchecked") public List<MailingList> findMailingLists(int skip, int count) { Query q = this.createNamedQuery("AllMailingLists"); if (skip >= 0) q.setFirstResult(skip); if (count >= 0) q.setMaxResults(count); return q.getResultList(); } /** * Finds a mailing list with the specified query. * @param query is a literal string to match in the text * @param skip can be -1 for no skip * @param count can be -1 for no limit */ @SuppressWarnings("unchecked") public List<MailingList> findMailingLists(String query, int skip, int count) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding MailingLists with query: {0}", query); Query q = this.createNamedQuery("SearchMailingLists"); q.setParameter("name", like(query)); q.setParameter("email", like(query)); q.setParameter("url", like(query)); q.setParameter("description", like(query)); if (skip >= 0) q.setFirstResult(skip); if (count >= 0) q.setMaxResults(count); return q.getResultList(); } /** * @return the total number of lists on this server */ public int countLists() { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Counting all mailing lists"); Query q = this.createNamedQuery("CountMailingLists"); Number n = (Number) q.getSingleResult(); return n.intValue(); } /** * @return the total number of lists on this server based on the string query */ public int countLists(String query) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Counting mailing lists with query: {0}", query); Query q = this.createNamedQuery("CountMailingListsQuery"); q.setParameter("name", like(query)); q.setParameter("email", like(query)); q.setParameter("url", like(query)); q.setParameter("description", like(query)); Number n = (Number) q.getSingleResult(); return n.intValue(); } /** * @return all the threads for the list */ @SuppressWarnings("unchecked") public List<Mail> findMailByList(Long listId, int skip, int count) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding all mail for list {0}", listId); Query q = this.createNamedQuery("MailByList"); q.setParameter("listId", listId); if (skip >= 0) q.setFirstResult(skip); if (count >= 0) q.setMaxResults(count); return q.getResultList(); } /** * @return all of the mail on a list */ public int countMailByList(Long listId) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Counting all mail for list {0}", listId); Query q = this.createNamedQuery("CountMailByList"); q.setParameter("listId", listId); Number n = (Number) q.getSingleResult(); return n.intValue(); } /** * @return any subscriptions which have the specified role. */ @SuppressWarnings("unchecked") public List<Subscription> findSubscriptionsByRole(Long roleId) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding Subscriptions with role {0}", roleId); Query q = this.createNamedQuery("SubscriptionsByRoleId"); q.setParameter("roleId", roleId); return q.getResultList(); } /** * @return all Mail for the list which has a not null HoldType */ @SuppressWarnings("unchecked") public List<Mail> findMailHeld(Long listId, int skip, int count) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding held mail for list {0}", listId); Query q = this.createNamedQuery("HeldMail"); q.setParameter("listId", listId); if (skip >= 0) q.setFirstResult(skip); if (count >= 0) q.setMaxResults(count); return q.getResultList(); } /** * @return the number of messages in a held state on a list. */ public int countHeldMessages(Long listId) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Counting held mail for list {0}", listId); Query q = this.createNamedQuery("HeldMailCount"); q.setParameter("listId", listId); Number n = (Number) q.getSingleResult(); return n.intValue(); } /** * @return the number of held subscriptions on the list */ public int countHeldSubscriptions(Long listId) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Counting held subscriptions for list {0}", listId); Query q = this.createNamedQuery("HeldSubscriptionCount"); q.setParameter("listId", listId); Number n = (Number) q.getSingleResult(); return n.intValue(); } /** * @return all Persons who are site admins */ @SuppressWarnings("unchecked") public List<Person> findSiteAdmins() { log.log(Level.FINE,"Finding all site admins"); Query q = this.createNamedQuery("SiteAdmin"); return q.getResultList(); } /** * @return the number of subscribers on a list */ public int countSubscribers(Long listId) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Counting subscribers of list: {0}", listId); Query q = this.createNamedQuery("CountSubscribersOnList"); q.setParameter("listId", listId); Number n = (Number) q.getSingleResult(); return n.intValue(); } /** * @return the total number of mails on the server. */ public int countMail() { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Counting all mail"); Query q = this.createNamedQuery("CountMail"); Number n = (Number) q.getSingleResult(); return n.intValue(); } /** * @return the total number of Persons on this server. */ public int countPeople() { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Counting all people"); Query q = this.createNamedQuery("CountPerson"); Number n = (Number) q.getSingleResult(); return n.intValue(); } /** * @return the number of subscribers on a list based on a String query */ public int countSubscribers(Long listId, String query) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Counting subscribers on list: {0} with query: {1}", new Object[]{listId,query}); Query q = this.createNamedQuery("CountSubscribersOnListQuery"); q.setParameter("listId", listId); q.setParameter("name", like(query)); q.setParameter("email", like(query)); //q.setParameter("note", like(query)); Number n = (Number) q.getSingleResult(); return n.intValue(); } /** * @param skip can be -1 for no skip * @param count can be -1 for no limit * * @return the paginated list of subscibers */ @SuppressWarnings("unchecked") public List<Subscription> findSubscribers(Long listId, int skip, int count) { Query q = this.createNamedQuery("SubscribersOnList"); q.setParameter("listId", listId); if (skip >= 0) q.setFirstResult(skip); if (count >= 0) q.setMaxResults(count); return q.getResultList(); } /** * Limit the number of subscribers on a list based on a String query * * @param skip can be -1 for no skip * @param count can be -1 for no limit */ @SuppressWarnings("unchecked") public List<Subscription> findSubscribers(Long listId, String query, int skip, int count) { Query q = this.createNamedQuery("SubscribersOnListQuery"); q.setParameter("listId", listId); q.setParameter("name", like(query)); q.setParameter("email", like(query)); //q.setParameter("note", like(query)); if (skip >= 0) q.setFirstResult(skip); if (count >= 0) q.setMaxResults(count); return q.getResultList(); } /** * @return all the soft holds associated with any email address * that the person owns. The resulting mail objects are editable. */ @SuppressWarnings("unchecked") public List<Mail> findSoftHoldsForPerson(Long personId) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding soft mail holds for person {0}", personId); Query q = this.createNamedQuery("SoftHoldsByPerson"); q.setParameter("personId", personId); return q.getResultList(); } /** Helper method makes "like" queries possible */ private final String like(String query) { return "%" + query + "%"; } /** * @return all the mail created since a particular arrival date */ @SuppressWarnings("unchecked") public List<Mail> findMailSince(Date when) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding mail since {0}", when); Query q = this.createNamedQuery("MailSince"); q.setParameter("since", when); return q.getResultList(); } /** * Gets all subscriptionholds older than the specified date. */ @SuppressWarnings("unchecked") public List<SubscriptionHold> findHeldSubscriptionsOlderThan(Date cutoff) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding held subs older than {0}", cutoff); Query q = this.createNamedQuery("HeldSubscriptionsOlderThan"); q.setParameter("cutoff", cutoff); return q.getResultList(); } /** * Gets all held mail older than a certain date. */ @SuppressWarnings("unchecked") public List<Mail> findHeldMailOlderThan(Date cutoff) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding held mail older than {0}", cutoff); Query q = this.createNamedQuery("HeldMailOlderThan"); q.setParameter("cutoff", cutoff); return q.getResultList(); } /** * Gets the last piece of held mail sent by the person to any list. * @param excludeMailId is the id of mail that shouldn't be considered. * @return null if there wasn't any. */ public Mail findLastMailHeldFrom(String senderEmail, Long excludeMailId) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding the last held mail from {0}", senderEmail); senderEmail = Validator.normalizeEmail(senderEmail); Query q = this.createNamedQuery("HeldMailFrom"); q.setParameter("sender", senderEmail); q.setParameter("excluding", excludeMailId); q.setMaxResults(1); return (Mail)q.getSingleResult(); } /** * Counts the number of held messages from an address since a particular date. */ public int countRecentHeldMail(String senderEmail, Date since) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Counting recent held mail from {0}", senderEmail); senderEmail = Validator.normalizeEmail(senderEmail); Query q = this.createNamedQuery("CountRecentHeldMailFrom"); q.setParameter("sender", senderEmail); q.setParameter("since", since); return ((Number)q.getSingleResult()).intValue(); } /** * Finds most recent mail with the constraints. * * @param listId the mailing list to look in * @param subj the subject to match * @param cutoff the oldest mail to consider * @param count the max number of results to return */ @SuppressWarnings("unchecked") public List<Mail> findRecentMailBySubject(Long listId, String subj, Date cutoff, int count) { if (log.isLoggable(Level.FINE)) log.log(Level.FINE,"Finding mail with subject {0} younger than {1}", new Object[]{subj,cutoff}); Query q = this.createNamedQuery("RecentMailBySubject"); q.setParameter("listId", listId); q.setParameter("subject", subj); q.setParameter("cutoff", cutoff); q.setMaxResults(count); return q.getResultList(); } @Override public void persist(Object arg0) { this.base.persist(arg0); } @Override public <T> T merge(T arg0) { return this.base.merge(arg0); } @Override public void remove(Object arg0) { this.base.remove(arg0); } @Override public <T> T find(Class<T> arg0, Object arg1) { return this.base.find(arg0, arg1); } @Override public <T> T getReference(Class<T> arg0, Object arg1) { return this.base.getReference(arg0, arg1); } @Override public void flush() { this.base.flush(); } @Override public void setFlushMode(FlushModeType arg0) { this.base.setFlushMode(arg0); } @Override public FlushModeType getFlushMode() { return this.base.getFlushMode(); } @Override public void lock(Object arg0, LockModeType arg1) { this.base.lock(arg0, arg1); } @Override public void refresh(Object arg0) { this.base.refresh(arg0); } @Override public void clear() { this.base.clear(); } @Override public boolean contains(Object arg0) { return this.base.contains(arg0); } @Override public Query createQuery(String arg0) { return this.base.createQuery(arg0); } @Override public Query createNamedQuery(String arg0) { return this.base.createNamedQuery(arg0); } @Override public Query createNativeQuery(String arg0) { return this.base.createNativeQuery(arg0); } @Override @SuppressWarnings("rawtypes") public Query createNativeQuery(String arg0, Class arg1) { return this.base.createNativeQuery(arg0, arg1); } @Override public Query createNativeQuery(String arg0, String arg1) { return this.base.createNativeQuery(arg0, arg1); } @Override public void joinTransaction() { this.base.joinTransaction(); } @Override public Object getDelegate() { return this.base.getDelegate(); } @Override public void close() { this.base.close(); } @Override public boolean isOpen() { return this.base.isOpen(); } @Override public EntityTransaction getTransaction() { return this.base.getTransaction(); } @Override public <T> T find(Class<T> arg0, Object arg1, LockModeType arg2) { return this.base.find(arg0, arg1, arg2); } @Override public EntityManagerFactory getEntityManagerFactory() { return this.getEntityManagerFactory(); } @Override public LockModeType getLockMode(Object arg0) { return this.base.getLockMode(arg0); } @Override @SuppressWarnings({ "unchecked", "rawtypes" }) public Map getProperties() { return this.base.getProperties(); } @Override public void refresh(Object arg0, LockModeType arg1) { this.base.refresh(arg0, arg1); } @Override public <T> TypedQuery<T> createNamedQuery(String arg0, Class<T> arg1) { return this.base.createNamedQuery(arg0, arg1); } @Override public <T> TypedQuery<T> createQuery(CriteriaQuery<T> arg0) { return this.base.createQuery(arg0); } @Override public void detach(Object arg0) { this.base.detach(arg0); } @Override public CriteriaBuilder getCriteriaBuilder() { return this.base.getCriteriaBuilder(); } @Override public Metamodel getMetamodel() { return this.base.getMetamodel(); } @Override public void lock(Object arg0, LockModeType arg1, Map<String, Object> arg2) { this.base.lock(arg0, arg1, arg2); } @Override public void refresh(Object arg0, Map<String, Object> arg1) { this.base.refresh(arg0, arg1); } @Override public void refresh(Object arg0, LockModeType arg1, Map<String, Object> arg2) { this.base.refresh(arg0, arg1, arg2); } @Override public void setProperty(String arg0, Object arg1) { this.base.setProperty(arg0, arg1); } @Override public <T> T unwrap(Class<T> arg0) { return this.base.unwrap(arg0); } @Override public <T> T find(Class<T> paramClass, Object paramObject, Map<String, Object> paramMap) { return this.base.find(paramClass, paramClass, paramMap); } @Override public <T> T find(Class<T> paramClass, Object paramObject, LockModeType paramLockModeType, Map<String, Object> paramMap) { return this.base.find(paramClass, paramObject, paramLockModeType, paramMap); } @Override public <T> TypedQuery<T> createQuery(String paramString, Class<T> paramClass) { return this.base.createQuery(paramString, paramClass); } }