package de.cinovo.cloudconductor.server.dao.hibernate; import java.security.Principal; import javax.persistence.EntityNotFoundException; import org.apache.cxf.phase.PhaseInterceptorChain; import org.apache.cxf.security.SecurityContext; import org.joda.time.DateTime; import org.springframework.transaction.annotation.Transactional; import de.cinovo.cloudconductor.api.model.INamed; import de.cinovo.cloudconductor.server.dao.IAuditedEntity; import de.cinovo.cloudconductor.server.model.EAuditLog; import de.cinovo.cloudconductor.server.model.IVersionized; import de.cinovo.cloudconductor.server.model.enums.AuditCategory; import de.cinovo.cloudconductor.server.model.enums.AuditType; import de.taimos.dao.IEntity; import de.taimos.dao.hibernate.EntityDAOHibernate; /** * Copyright 2014 Cinovo AG<br> * <br> * * @author psigloch * * @param <E> the entity type * @param <I> the id type */ public abstract class AAuditedEntityHib<E extends IEntity<I>, I> extends EntityDAOHibernate<E, I> implements IAuditedEntity<E, I> { /** * @return the audit category of the element */ protected abstract AuditCategory getAuditCategory(); @SuppressWarnings("unchecked") @Override @Transactional public E save(final E element, String auditMessage) { E result = super.save(element); AuditType type = this.getAuditType(element); if ((element instanceof IVersionized) && (((IVersionized<?>) element).getVersion() instanceof Number)) { this.generateAuditLog(type, auditMessage, element.getId(), ((IVersionized<Number>) element).getVersion(), ((IVersionized<Number>) result).getVersion()); } else { this.generateAuditLog(type, auditMessage, element.getId()); } return result; } @SuppressWarnings("unchecked") @Transactional private AuditType getAuditType(E element) { if (element instanceof IVersionized) { IVersionized<Long> versioned = (IVersionized<Long>) element; if (versioned.isDeleted()) { return AuditType.DELETE; } if ((versioned.getId() == null) && (versioned.getVersion() < 1)) { return AuditType.NEW; } return AuditType.CHANGE; } if ((element.getId() == null)) { return AuditType.NEW; } return AuditType.CHANGE; } @SuppressWarnings("unchecked") @Override @Transactional public E save(final E element) { E result = super.save(element); AuditType type = this.getAuditType(element); String auditMessage; switch (type) { case CHANGE: auditMessage = this.getChangeEntry(element); break; case DELETE: auditMessage = this.getDeleteEntry(element); break; case NEW: auditMessage = this.getNewEntry(element); break; default: auditMessage = ""; break; } if ((element instanceof IVersionized) && (((IVersionized<?>) element).getVersion() instanceof Number)) { this.generateAuditLog(type, auditMessage, element.getId(), ((IVersionized<Number>) element).getVersion(), ((IVersionized<Number>) result).getVersion()); } else { this.generateAuditLog(type, auditMessage, element.getId()); } return result; } @SuppressWarnings("unchecked") @Override @Transactional public void delete(final E element, String auditMessage) { super.delete(element); if ((element instanceof IVersionized) && (((IVersionized<?>) element).getVersion() instanceof Number)) { this.generateAuditLog(AuditType.DELETE, auditMessage, element.getId(), ((IVersionized<Number>) element).getVersion(), null); } else { this.generateAuditLog(AuditType.DELETE, auditMessage, element.getId(), null, null); } } @SuppressWarnings("unchecked") @Override @Transactional public void delete(final E element) { super.delete(element); if ((element instanceof IVersionized) && (((IVersionized<?>) element).getVersion() instanceof Number)) { this.generateAuditLog(AuditType.DELETE, this.getDeleteEntry(element), element.getId(), ((IVersionized<Number>) element).getVersion(), null); } else { this.generateAuditLog(AuditType.DELETE, this.getDeleteEntry(element), element.getId()); } } @SuppressWarnings("unchecked") @Override @Transactional public void deleteById(final I id) { final E element = this.findById(id); if (element == null) { throw new EntityNotFoundException(); } this.entityManager.remove(element); if ((element instanceof IVersionized) && (((IVersionized<?>) element).getVersion() instanceof Number)) { this.generateAuditLog(AuditType.DELETE, this.getDeleteEntry(element), element.getId(), ((IVersionized<Number>) element).getVersion(), null); } else { this.generateAuditLog(AuditType.DELETE, this.getDeleteEntry(element), element.getId()); } } private String getUser() { SecurityContext sc = PhaseInterceptorChain.getCurrentMessage().get(SecurityContext.class); Principal p = sc.getUserPrincipal(); if (p == null) { return "REST-CALL"; } return p.getName(); } private void generateAuditLog(AuditType type, String message, I elementId) { this.generateAuditLog(type, message, elementId, null, null); } private void generateAuditLog(AuditType type, String message, I elementId, Number origRev, Number newRev) { EAuditLog log = new EAuditLog(); log.setAuditType(type); log.setCategory(this.getAuditCategory()); log.setTimestamp(DateTime.now().getMillis()); log.setUsername(this.getUser()); log.setEntry(message); if ((elementId != null) && (elementId instanceof Number)) { log.setElementId(((Number) elementId).longValue()); } if (origRev != null) { log.setOrigRev(origRev.longValue()); } if (newRev != null) { log.setNewRev(newRev.longValue()); } this.entityManager.merge(log); } protected String getDeleteEntry(E element) { if (element instanceof INamed) { return "Deleted element " + ((INamed) element).getName(); } return "Deleted element"; } protected String getChangeEntry(E element) { if (element instanceof INamed) { return "Changed element " + ((INamed) element).getName(); } return "Changed element"; } protected String getNewEntry(E element) { if (element instanceof INamed) { return "New element " + ((INamed) element).getName() + " created"; } return "New element created"; } }