package com.ctp.cdi.query.audit; import java.util.Collections; import java.util.Set; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.inject.Inject; import org.jboss.solder.properties.Property; import org.jboss.solder.properties.query.AnnotatedPropertyCriteria; import org.jboss.solder.properties.query.PropertyQueries; import org.jboss.solder.properties.query.PropertyQuery; import org.jboss.solder.reflection.AnnotationInstanceProvider; class PrincipalProvider extends AuditProvider { @Inject private BeanManager manager; @Override public void prePersist(Object entity) { updatePrincipal(entity); } @Override public void preUpdate(Object entity) { updatePrincipal(entity); } private void updatePrincipal(Object entity) { PropertyQuery<Object> query = PropertyQueries.<Object>createQuery(entity.getClass()) .addCriteria(new AnnotatedPropertyCriteria(ModifiedBy.class)); for (Property<Object> property : query.getWritableResultList()) { setProperty(entity, property); } } private void setProperty(Object entity, Property<Object> property) { try { Object value = resolvePrincipal(entity, property); property.setValue(entity, value); log.debugv("Updated {0} with {1}", propertyName(entity, property), value); } catch (Exception e) { throw new AuditPropertyException("Failed to write principal to " + propertyName(entity, property), e); } } private Object resolvePrincipal(Object entity, Property<Object> property) { AnnotationInstanceProvider provider = new AnnotationInstanceProvider(); CurrentUser principal = provider.get(CurrentUser.class, Collections.<String, Object>emptyMap()); Class<?> propertyClass = property.getJavaClass(); Set<Bean<?>> beans = manager.getBeans(propertyClass, principal); if (!beans.isEmpty() && beans.size() == 1) { Bean<?> bean = beans.iterator().next(); Object result = manager.getReference(bean, propertyClass, manager.createCreationalContext(bean)); return result; } throw new IllegalArgumentException("Principal " + (beans.isEmpty() ? "not found" : "not unique") + " for " + propertyName(entity, property)); } }