package org.jboss.seam.security;
import static org.jboss.seam.ScopeType.APPLICATION;
import static org.jboss.seam.annotations.Install.BUILT_IN;
import java.io.Serializable;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.Query;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.intercept.BypassInterceptors;
import org.jboss.seam.annotations.security.TokenUsername;
import org.jboss.seam.annotations.security.TokenValue;
import org.jboss.seam.core.Expressions;
import org.jboss.seam.core.Expressions.ValueExpression;
import org.jboss.seam.security.management.IdentityManagementException;
import org.jboss.seam.util.AnnotatedBeanProperty;
/**
* A TokenStore implementation, stores tokens inside a database table.
*
* @author Shane Bryzak
*/
@Name("org.jboss.seam.security.tokenStore")
@Install(precedence = BUILT_IN, value=false)
@Scope(APPLICATION)
@BypassInterceptors
public class JpaTokenStore implements TokenStore, Serializable
{
private Class tokenClass;
private ValueExpression<EntityManager> entityManager;
private AnnotatedBeanProperty<TokenUsername> tokenUsernameProperty;
private AnnotatedBeanProperty<TokenValue> tokenValueProperty;
@Create
public void create()
{
if (entityManager == null)
{
entityManager = Expressions.instance().createValueExpression("#{entityManager}", EntityManager.class);
}
tokenUsernameProperty = new AnnotatedBeanProperty<TokenUsername>(tokenClass, TokenUsername.class);
tokenValueProperty = new AnnotatedBeanProperty<TokenValue>(tokenClass, TokenValue.class);
if (!tokenUsernameProperty.isSet())
{
throw new IllegalStateException("Invalid tokenClass " + tokenClass.getName() +
" - required annotation @TokenUsername not found on any Field or Method.");
}
if (!tokenValueProperty.isSet())
{
throw new IllegalStateException("Invalid tokenClass " + tokenClass.getName() +
" - required annotation @TokenValue not found on any Field or Method.");
}
}
public void createToken(String username, String value)
{
if (tokenClass == null)
{
throw new IllegalStateException("Could not create token, tokenClass not set");
}
try
{
Object token = tokenClass.newInstance();
tokenUsernameProperty.setValue(token, username);
tokenValueProperty.setValue(token, value);
lookupEntityManager().persist(token);
}
catch (Exception ex)
{
if (ex instanceof IdentityManagementException)
{
throw (IdentityManagementException) ex;
}
else
{
throw new IdentityManagementException("Could not create account", ex);
}
}
}
public boolean validateToken(String username, String value)
{
return lookupToken(username, value) != null;
}
public void invalidateToken(String username, String value)
{
Object token = lookupToken(username, value);
if (token != null)
{
lookupEntityManager().remove(token);
}
}
public void invalidateAll(String username)
{
Query query = lookupEntityManager().createQuery(
"select t from " + tokenClass.getName() + " t where " + tokenUsernameProperty.getName() +
" = :username")
.setParameter("username", username);
for (Object token : query.getResultList())
{
lookupEntityManager().remove(token);
}
}
public Object lookupToken(String username, String value)
{
try
{
Object token = lookupEntityManager().createQuery(
"select t from " + tokenClass.getName() + " t where " + tokenUsernameProperty.getName() +
" = :username and " + tokenValueProperty.getName() + " = :value")
.setParameter("username", username)
.setParameter("value", value)
.getSingleResult();
return token;
}
catch (NoResultException ex)
{
return null;
}
}
public Class getTokenClass()
{
return tokenClass;
}
public void setTokenClass(Class tokenClass)
{
this.tokenClass = tokenClass;
}
private EntityManager lookupEntityManager()
{
return entityManager.getValue();
}
public ValueExpression getEntityManager()
{
return entityManager;
}
public void setEntityManager(ValueExpression expression)
{
this.entityManager = expression;
}
}