/** * Copyright (c) 2009 - 2012 Red Hat, Inc. * * This software is licensed to you under the GNU General Public License, * version 2 (GPLv2). There is NO WARRANTY for this software, express or * implied, including the implied warranties of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. You should have received a copy of GPLv2 * along with this software; if not, see * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. * * Red Hat trademarks are not licensed under GPLv2. No permission is * granted to use or replicate Red Hat trademarks that are incorporated * in this software or its documentation. */ package org.candlepin.model; import com.google.common.collect.Iterables; import com.google.inject.Inject; import com.google.inject.persist.Transactional; import org.hibernate.criterion.Restrictions; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.persistence.Query; /** * ContentAccessCertificateCurator */ public class ContentAccessCertificateCurator extends AbstractHibernateCurator<ContentAccessCertificate> { private static Logger log = LoggerFactory.getLogger(ContentAccessCertificateCurator.class); @Inject public ContentAccessCertificateCurator() { super(ContentAccessCertificate.class); } @SuppressWarnings("unchecked") @Transactional public ContentAccessCertificate getForConsumer(Consumer c) { return (ContentAccessCertificate) currentSession().createCriteria(ContentAccessCertificate.class) .add(Restrictions.eq("consumer", c)) .uniqueResult(); } /** * Delete unneeded content access certs. * * @return the number of rows deleted. */ @Transactional public int deleteForOwner(Owner owner) { // So we must get ids for this owner, and then delete them @SuppressWarnings("unchecked") String hql = " SELECT cac.id, s.id " + " FROM Consumer c" + " JOIN c.owner o" + " JOIN c.contentAccessCert cac" + " JOIN cac.serial s" + " WHERE" + " o.key=:ownerkey"; Query query = this.getEntityManager().createQuery(hql); List<Object[]> rows = query.setParameter("ownerkey", owner.getKey()).getResultList(); Set<String> certsToDelete = new HashSet<String>(); Set<Long> certSerialsToRevoke = new HashSet<Long>(); for (Object[] row : rows) { if (row[0] != null) { certsToDelete.add((String) row[0]); } if (row[1] != null) { certSerialsToRevoke.add((Long) row[1]); } } // First ensure that we've marked all of the certificate serials as revoked. // Normally we would let the @PreRemove on CertificateSertial do this for us // when the certificate record is deleted, but since there's a potential for // a lot of certificates to exist for an Owner, we'll batch these updates. log.debug("Marked {} certificate serials as revoked.", revokeCertificateSerials(certSerialsToRevoke)); int removed = deleteContentAccessCerts(certsToDelete); log.debug("Deleted {} content access certificates.", removed); return removed; } /** * Mark the specified content access certificate serials as revoked. * * @param serialIdsToRevoke the ids of the serials to mark as revoked. * @return the number of serials that were marked as revoked. */ private int revokeCertificateSerials(Set<Long> serialIdsToRevoke) { String revokeHql = "UPDATE CertificateSerial SET revoked = true WHERE id IN (:serialsToRevoke)"; Query revokeQuery = this.getEntityManager().createQuery(revokeHql); int revokedCount = 0; for (List<Long> block : Iterables.partition(serialIdsToRevoke, getInBlockSize())) { revokedCount += revokeQuery.setParameter("serialsToRevoke", block).executeUpdate(); } return revokedCount; } private int deleteContentAccessCerts(Set<String> certIdsToDelete) { String hql = "DELETE from ContentAccessCertificate WHERE id IN (:certsToDelete)"; Query query = this.getEntityManager().createQuery(hql); String hql2 = "UPDATE Consumer set contentAccessCert = null WHERE " + "contentAccessCert.id IN (:certsToDelete)"; Query query2 = this.getEntityManager().createQuery(hql2); int removed = 0; for (List<String> block : Iterables.partition(certIdsToDelete, getInBlockSize())) { String param = block.toString(); query2.setParameter("certsToDelete", block).executeUpdate(); removed += query.setParameter("certsToDelete", block).executeUpdate(); } return removed; } }