/*******************************************************************************
* Copyright (C) 2011 John Casey.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package org.commonjava.web.user.data;
import static org.commonjava.web.user.model.GeneralizationUtils.generalizePermissions;
import static org.commonjava.web.user.model.GeneralizationUtils.generalizeRoles;
import static org.commonjava.web.user.model.GeneralizationUtils.generalizeUsers;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.List;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Produces;
import javax.inject.Inject;
import javax.inject.Qualifier;
import javax.inject.Singleton;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Root;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import org.commonjava.util.logging.Logger;
import org.commonjava.web.user.model.Permission;
import org.commonjava.web.user.model.Role;
import org.commonjava.web.user.model.User;
@Singleton
public class DBUserDataBackend
implements UserDataBackend
{
private final Logger logger = new Logger( getClass() );
@Inject
@UserRepository
private EntityManager em;
@Inject
private Event<User> userEventSrc;
@Inject
private Event<Role> roleEventSrc;
@Inject
private Event<Permission> permissionEventSrc;
@Inject
private UserTransaction tx;
@Override
public boolean hasUser( final String username )
{
return em.contains( new User( username ) );
}
@Override
public boolean hasRole( final String name )
{
return em.contains( new Role( name ) );
}
@Override
public boolean hasPermission( final String name )
{
return em.contains( new Permission( name ) );
}
@Override
public List<User> getUsers()
{
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<User> query = cb.createQuery( User.class );
final Root<User> root = query.from( User.class );
query.select( root )
.orderBy( cb.asc( root.get( "lastName" ) ), cb.asc( root.get( "firstName" ) ) );
return generalizeUsers( em.createQuery( query )
.getResultList() );
}
@Override
public List<Role> getRoles()
{
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<Role> query = cb.createQuery( Role.class );
final Root<Role> root = query.from( Role.class );
query.select( root )
.orderBy( cb.asc( root.get( "name" ) ) );
return generalizeRoles( em.createQuery( query )
.getResultList() );
}
@Override
public List<Permission> getPermissions()
{
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<Permission> query = cb.createQuery( Permission.class );
final Root<Permission> root = query.from( Permission.class );
query.select( root )
.orderBy( cb.asc( root.get( "name" ) ) );
return generalizePermissions( em.createQuery( query )
.getResultList() );
}
@Override
public User saveUser( final User user, final boolean autoCommit )
throws UserDataException
{
try
{
if ( autoCommit )
{
tx.begin();
}
em.joinTransaction();
boolean success = true;
try
{
em.persist( user );
}
catch ( final EntityExistsException e )
{
success = false;
logger.error( "\n\n\nUser exists: %s\n\n\n", e, user.getUsername() );
}
if ( autoCommit )
{
if ( success )
{
tx.commit();
}
else
{
tx.rollback();
}
}
userEventSrc.fire( user );
return user;
}
catch ( final NotSupportedException e )
{
throw new UserDataException( "Cannot save user: %s. Error: %s", e, user, e.getMessage() );
}
catch ( final SystemException e )
{
throw new UserDataException( "Cannot save user: %s. Error: %s", e, user, e.getMessage() );
}
catch ( final RollbackException e )
{
throw new UserDataException( "Cannot save user: %s. Error: %s", e, user, e.getMessage() );
}
catch ( final HeuristicMixedException e )
{
throw new UserDataException( "Cannot save user: %s. Error: %s", e, user, e.getMessage() );
}
catch ( final HeuristicRollbackException e )
{
throw new UserDataException( "Cannot save user: %s. Error: %s", e, user, e.getMessage() );
}
}
@Override
public Role saveRole( final Role role, final boolean autoCommit )
throws UserDataException
{
try
{
if ( autoCommit )
{
tx.begin();
}
em.joinTransaction();
boolean success = true;
try
{
em.persist( role );
}
catch ( final EntityExistsException e )
{
success = false;
logger.error( "\n\n\nRole exists: %s\n\n\n", e, role.getName() );
}
if ( autoCommit )
{
if ( success )
{
tx.commit();
}
else
{
tx.rollback();
}
}
roleEventSrc.fire( role );
return role;
}
catch ( final NotSupportedException e )
{
throw new UserDataException( "Cannot save role: %s. Error: %s", e, role, e.getMessage() );
}
catch ( final SystemException e )
{
throw new UserDataException( "Cannot save role: %s. Error: %s", e, role, e.getMessage() );
}
catch ( final RollbackException e )
{
throw new UserDataException( "Cannot save role: %s. Error: %s", e, role, e.getMessage() );
}
catch ( final HeuristicMixedException e )
{
throw new UserDataException( "Cannot save role: %s. Error: %s", e, role, e.getMessage() );
}
catch ( final HeuristicRollbackException e )
{
throw new UserDataException( "Cannot save role: %s. Error: %s", e, role, e.getMessage() );
}
}
@Override
public Permission savePermission( final Permission perm, final boolean autoCommit )
throws UserDataException
{
try
{
if ( autoCommit )
{
tx.begin();
}
em.joinTransaction();
boolean success = true;
try
{
em.persist( perm );
}
catch ( final EntityExistsException e )
{
success = false;
logger.error( "\n\n\nPermission exists: %s\n\n\n", e, perm.getName() );
}
if ( autoCommit )
{
if ( success )
{
tx.commit();
}
else
{
tx.rollback();
}
}
permissionEventSrc.fire( perm );
return perm;
}
catch ( final NotSupportedException e )
{
throw new UserDataException( "Cannot save permission: %s. Error: %s", e, perm, e.getMessage() );
}
catch ( final SystemException e )
{
throw new UserDataException( "Cannot save permission: %s. Error: %s", e, perm, e.getMessage() );
}
catch ( final RollbackException e )
{
throw new UserDataException( "Cannot save permission: %s. Error: %s", e, perm, e.getMessage() );
}
catch ( final HeuristicMixedException e )
{
throw new UserDataException( "Cannot save permission: %s. Error: %s", e, perm, e.getMessage() );
}
catch ( final HeuristicRollbackException e )
{
throw new UserDataException( "Cannot save permission: %s. Error: %s", e, perm, e.getMessage() );
}
}
@Override
public User getUser( final String username )
{
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<User> query = cb.createQuery( User.class );
final Root<User> root = query.from( User.class );
query.select( root )
.where( cb.equal( root.get( "username" ), username ) );
User user = null;
try
{
// TODO: cleaner way to check for user existence...
user = em.createQuery( query )
.getSingleResult();
}
catch ( final NoResultException e )
{
logger.debug( "Cannot find user: %s. Error: %s", e, username, e.getMessage() );
}
return user;
}
@Override
public Permission getPermission( final String permissionName )
{
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<Permission> query = cb.createQuery( Permission.class );
final Root<Permission> root = query.from( Permission.class );
query.select( root )
.where( cb.equal( root.get( "name" ), permissionName ) );
Permission perm = null;
try
{
// TODO: cleaner way to check for user existence...
perm = em.createQuery( query )
.getSingleResult();
}
catch ( final NoResultException e )
{
logger.debug( "Cannot find permission: %s. Error: %s", e, permissionName, e.getMessage() );
}
return perm;
}
@Override
public Role getRole( final String roleName )
{
final CriteriaBuilder cb = em.getCriteriaBuilder();
final CriteriaQuery<Role> query = cb.createQuery( Role.class );
final Root<Role> root = query.from( Role.class );
query.select( root )
.where( cb.equal( root.get( "name" ), roleName ) );
Role role = null;
try
{
// TODO: cleaner way to check for user existence...
role = em.createQuery( query )
.getSingleResult();
}
catch ( final NoResultException e )
{
logger.debug( "Cannot find role: %s. Error: %s", e, roleName, e.getMessage() );
}
return role;
}
// public void onUserChanged( @Observes( notifyObserver = Reception.IF_EXISTS ) final User user )
// {
// loadData();
// }
//
// @PostConstruct
// public void loadData()
// {
// }
@Override
public void deletePermission( final String name )
throws UserDataException
{
try
{
final Permission perm = getPermission( name );
if ( perm == null )
{
throw new UserDataException( "No such permission: %s", name );
}
em.remove( perm );
}
catch ( final IllegalArgumentException e )
{
logger.debug( "Cannot remove permission: %s. Error: %s", e, name, e.getMessage() );
throw new UserDataException( "Cannot delete permission: %s. Error: %s", e, name, e.getMessage() );
}
}
@Override
public void deleteRole( final String name )
throws UserDataException
{
try
{
final Role role = getRole( name );
if ( role == null )
{
throw new UserDataException( "No such role: %s", name );
}
em.remove( role );
}
catch ( final IllegalArgumentException e )
{
logger.debug( "Cannot remove role: %s. Error: %s", e, name, e.getMessage() );
throw new UserDataException( "Cannot delete role: %s. Error: %s", e, name, e.getMessage() );
}
}
@Override
public void deleteUser( final String username )
throws UserDataException
{
try
{
final User user = getUser( username );
if ( user == null )
{
throw new UserDataException( "No such user: %s", username );
}
em.remove( user );
}
catch ( final IllegalArgumentException e )
{
logger.debug( "Cannot remove user: %s. Error: %s", e, username, e.getMessage() );
throw new UserDataException( "Cannot delete user: %s. Error: %s", e, username, e.getMessage() );
}
}
public static final class RepositoryProducer
{
@SuppressWarnings( "unused" )
@Produces
@UserRepository
@PersistenceContext
private EntityManager entityManager;
}
@Qualifier
@Target( { ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD } )
@Retention( RetentionPolicy.RUNTIME )
public @interface UserRepository
{
}
}