org.jboss.security.acl.JPAPersistenceStrategy Maven / Gradle / Ivy
package org.jboss.security.acl;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.NoResultException;
import javax.persistence.Persistence;
import org.jboss.security.PicketBoxMessages;
import org.jboss.security.authorization.Resource;
/**
*
* Implementation of {@code ACLPersistenceStrategy} that uses the Java Persistence API (JPA) to
* persist the {@code ACL}s.
*
*
* @author Stefan Guilhen
*/
public class JPAPersistenceStrategy implements ACLPersistenceStrategy
{
// in memory cache of the created ACLs.
private final Map aclMap;
private final EntityManagerFactory managerFactory;
private final ACLResourceFactory resourceFactory;
public JPAPersistenceStrategy()
{
this(null);
}
public JPAPersistenceStrategy(ACLResourceFactory resourceFactory)
{
this.aclMap = new HashMap();
this.managerFactory = Persistence.createEntityManagerFactory("ACL");
this.resourceFactory = resourceFactory;
}
/*
* (non-Javadoc)
* @see org.jboss.security.acl.ACLProvider#createACL(org.jboss.security.authorization.Resource)
*/
public ACL createACL(Resource resource)
{
return this.createACL(resource, new ArrayList());
}
/*
* (non-Javadoc)
* @see org.jboss.security.acl.ACLProvider#createACL(org.jboss.security.authorization.Resource, java.util.Collection)
*/
public ACL createACL(Resource resource, Collection entries)
{
if (resource == null)
throw PicketBoxMessages.MESSAGES.invalidNullArgument("resource");
// check the cache first.
ACL acl = this.aclMap.get(resource);
if (acl == null)
{
EntityManager entityManager = this.managerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
try
{
// create a new ACL and persist it to the database.
acl = new ACLImpl(resource, entries);
entityManager.persist(acl);
// add the newly-created ACL to the cache.
this.aclMap.put(resource, acl);
transaction.commit();
}
catch (RuntimeException re)
{
re.printStackTrace();
transaction.rollback();
}
finally
{
entityManager.close();
}
}
return acl;
}
/*
* (non-Javadoc)
* @see org.jboss.security.acl.ACLProvider#removeACL(org.jboss.security.acl.ACL)
*/
public boolean removeACL(ACL acl)
{
return this.removeACL(acl.getResource());
}
/*
* (non-Javadoc)
* @see org.jboss.security.acl.ACLProvider#removeACL(org.jboss.security.authorization.Resource)
*/
public boolean removeACL(Resource resource)
{
boolean result = false;
EntityManager entityManager = this.managerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
try
{
// find the ACL associated with the specified resource and remove it from the database.
ACL acl = this.findACLByResource(resource, entityManager);
if (acl != null)
{
entityManager.remove(acl);
// remove the ACL from the cache.
result = this.aclMap.remove(resource) != null;
}
transaction.commit();
}
catch (RuntimeException re)
{
re.printStackTrace();
transaction.rollback();
}
finally
{
entityManager.close();
}
return result;
}
/*
* (non-Javadoc)
* @see org.jboss.security.acl.ACLProvider#getACL(org.jboss.security.authorization.Resource)
*/
public ACL getACL(Resource resource)
{
// check the cache first.
ACL acl = this.aclMap.get(resource);
if (acl == null)
{
EntityManager entityManager = this.managerFactory.createEntityManager();
try
{
acl = this.findACLByResource(resource, entityManager);
if (acl != null)
this.aclMap.put(resource, acl);
}
finally
{
entityManager.close();
}
}
return acl;
}
/*
* (non-Javadoc)
* @see org.jboss.security.acl.ACLPersistenceStrategy#getACLs()
*/
@SuppressWarnings("unchecked")
public Collection getACLs()
{
Collection acls = null;
EntityManager entityManager = this.managerFactory.createEntityManager();
try
{
acls = entityManager.createQuery("SELECT a FROM ACLImpl a").getResultList();
if (acls != null && this.resourceFactory != null)
{
for (ACL acl : acls)
{
ACLImpl impl = (ACLImpl) acl;
String[] resourceName = impl.getResourceAsString().split(":");
impl.setResource(this.resourceFactory.instantiateResource(resourceName[0], resourceName[1]));
}
}
}
finally
{
entityManager.close();
}
return acls;
}
/*
* (non-Javadoc)
* @see org.jboss.security.acl.ACLProvider#updateACL(org.jboss.security.acl.ACL)
*/
public boolean updateACL(ACL acl)
{
if (((ACLImpl) acl).getACLId() == 0)
return false;
EntityManager entityManager = this.managerFactory.createEntityManager();
EntityTransaction transaction = entityManager.getTransaction();
transaction.begin();
try
{
for (ACLEntry entry : acl.getEntries())
{
// persist the new entries that might have been added to the ACL.
ACLEntryImpl entryImpl = (ACLEntryImpl) entry;
if (entryImpl.getACLEntryId() == 0)
entityManager.persist(entryImpl);
}
// merge will take care of the entries that might have been removed.
entityManager.merge(acl);
// update the cache.
this.aclMap.put(acl.getResource(), acl);
transaction.commit();
return true;
}
catch (RuntimeException re)
{
re.printStackTrace();
transaction.rollback();
}
finally
{
entityManager.close();
}
return false;
}
/**
*
* Searches the database for the {@code ACL} associated with the specified resource.
*
*
* @param resource the {@code Resource} that is associated with the {@code ACL} being searched.
* @param entityManager the {@code EntityManager} used to search the database.
* @return the {@code ACL} retrieved from the database, or {@code null} if no {@code ACL} could be found.
*/
private ACLImpl findACLByResource(Resource resource, EntityManager entityManager)
{
ACLImpl acl = null;
try
{
acl = (ACLImpl) entityManager.createQuery(
"SELECT a FROM ACLImpl a WHERE a.resourceAsString LIKE '" + Util.getResourceAsString(resource) + "'")
.getSingleResult();
acl.setResource(resource);
}
catch (NoResultException nre)
{
// ignore the exception when no ACL could be found for the given resource.
}
return acl;
}
}