Java tutorial
/*$Id: AuditInterceptorH3.java 12055 2008-12-06 20:24:08Z jens $*/ /* **************************************************************************** * * * (c) Copyright 2008 ABM-utvikling * * * * This program is free software; you can redistribute it and/or modify it * * under the terms of the GNU General Public License as published by the * * Free Software Foundation; either version 2 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 General * * Public License for more details. http://www.gnu.org/licenses/gpl.html * * * **************************************************************************** */ package no.abmu.common.hibernate3; import java.io.Serializable; import java.lang.reflect.InvocationTargetException; import java.util.Arrays; import java.util.Date; import java.util.HashSet; import java.util.Iterator; import java.util.Set; import no.abmu.common.AuditEntry; import no.abmu.common.Auditable; import org.apache.commons.beanutils.BeanUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hibernate.CallbackException; import org.hibernate.EmptyInterceptor; import org.hibernate.HibernateException; import org.hibernate.ObjectNotFoundException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.type.Type; import org.springframework.orm.hibernate3.SessionFactoryUtils; /** * AuditInterceptor. * * @author Jens.Vindvad@abm-utvikling.no * @author $Author: jens $ * @version $Rev: 12055 $ * date $Date: 2008-12-06 21:24:08 +0100 (Sat, 06 Dec 2008) $ * copyright ABM-Utvikling */ public class AuditInterceptorH3 extends EmptyInterceptor { private static final Log logger = (Log) LogFactory.getLog(AuditInterceptorH3.class); /** * New history entries, found in onFlushDirty. */ //TODO thread local?? // private final Map histories = new HashMap(); private static final int MAX_LEN = 10; private SessionFactory sessionFactory; /** * Create a new Interceptor, recording the changes under the given userName. */ public AuditInterceptorH3() { } public SessionFactory getSessionFactory() { return sessionFactory; } public void setSessionFactory(SessionFactory sessionFactory) { this.sessionFactory = sessionFactory; } /* * @see Interceptor#onLoad(java.lang.Object, java.io.Serializable, * java.lang.Object[], java.lang.String[], net.sf.hibernate.type.Type[]) */ public boolean onLoad(Object obj, Serializable id, Object[] values, String[] properties, Type[] types) { // logger.info("onLoad"); return false; } /** * Record the changes in the HashMap. Unfortunately, these changes can't be * done immediately (TransientObjectException), so they are recorded in a * seperate Set. * * @see Interceptor#onFlushDirty(java.lang.Object, java.io.Serializable, * java.lang.Object[], java.lang.Object[], java.lang.String[], * net.sf.hibernate.type.Type[]) */ public boolean onFlushDirty(Object obj, Serializable id, Object[] newValues, Object[] oldValues, String[] properties, Type[] types) { if (logger.isDebugEnabled()) { logger.debug("Updating " + obj + " with id " + id + " new=" + (newValues == null ? "null" : Arrays.asList(newValues).toString()) + " old=" + (oldValues == null ? "null" : Arrays.asList(oldValues).toString()) + " props=" + Arrays.asList(properties)); } if (!(obj instanceof Auditable)) { return false; } Auditable h = (Auditable) obj; Session session = null; Session newSession = null; try { session = SessionFactoryUtils.getSession(getSessionFactory(), true); newSession = sessionFactory.openSession(session.connection()); Auditable oldObject = null; try { oldObject = (Auditable) newSession.load(obj.getClass(), h.getId()); } catch (ObjectNotFoundException e) { if (logger.isDebugEnabled()) { logger.debug("nada if object not already saved"); } //nada if object not already saved } if (oldValues == null && newValues == null) { return false; } for (int i = 0; i < properties.length; i++) { // Skip the historyEntries if (properties[i].equals("auditEntries")) { continue; } Object newValue = null; Object oldValue = null; try { newValue = BeanUtils.getSimpleProperty(obj, properties[i]); oldValue = oldObject == null ? null : BeanUtils.getSimpleProperty(oldObject, properties[i]); } catch (IllegalAccessException e) { String message = "Cannot access property " + properties[i] + " in class " + obj.getClass().getName(); logger.error(message, e); throw new CallbackException(message, e); } catch (InvocationTargetException e) { String message = "Problem when reading " + properties[i] + " in class " + obj.getClass().getName(); logger.error(message, e); throw new CallbackException(message, e); } catch (NoSuchMethodException e) { String message = "No setter for property " + properties[i] + " in class " + obj.getClass().getName(); logger.error(message, e); throw new CallbackException(message, e); } if (oldValue == null && newValue == null) { continue; } // TO DO FIX THIS. 2008.12.03 /* if (newValue instanceof PersistentCollection) { // Collections must be compared against the snapshot PersistentCollection collection = (PersistentCollection) newValues[i]; if (!collection.isDirectlyAccessible()) { continue; } // retrieve Snapshot oldValue = collection.getCollectionSnapshot().getSnapshot(); if (oldValue instanceof Map && newValue instanceof Set) { // a Set is internally stored as Map oldValue = ((Map) oldValue).values(); } } */ if (oldValue != null && oldValue.equals(newValue)) { continue; } // Generate a new entry AuditEntry entry = new AuditEntry(); // entry.setWho(getName()); entry.setPointInTime(new Date()); entry.setWhat("update"); entry.setProperty(properties[i]); entry.setOldValue(format(oldValue)); entry.setNewValue(format(newValue)); entry.setIp(h.getEditCause() == null ? null : h.getEditCause().getIp()); entry.setReason(h.getEditCause() == null ? null : h.getEditCause().getReason()); if (logger.isDebugEnabled()) { logger.debug("Changed " + properties[i] + " from " + oldValue + " to " + newValue); } newSession.save(entry); if (logger.isInfoEnabled()) { logger.debug("added audit entry to " + h.getClass().getName()); } h.getAuditEntries().add(entry); } } catch (HibernateException e) { throw SessionFactoryUtils.convertHibernateAccessException(e); } finally { try { if (newSession != null) { newSession.flush(); newSession.close(); } } catch (HibernateException e) { throw SessionFactoryUtils.convertHibernateAccessException(e); } } //reset edit cause h.setEditCause(null); return false; } private String format(Object value) { String retVal = value == null ? "null" : value.toString(); if (retVal.length() > MAX_LEN) { retVal = retVal.substring(0, MAX_LEN); } return retVal; } /** * Record the creation of the object. * * @see net.sf.hibernate.Interceptor#onSave(java.lang.Object, * java.io.Serializable, java.lang.Object[], java.lang.String[], * net.sf.hibernate.type.Type[]) */ public boolean onSave(Object obj, Serializable id, Object[] newValues, String[] properties, Type[] types) { if (!(obj instanceof Auditable)) { return false; } Auditable h = (Auditable) obj; if (logger.isDebugEnabled()) { logger.debug("Inserting class " + obj.getClass().getName() + " : " + obj + " with id " + id + " new=" + Arrays.asList(newValues) + " props=" + Arrays.asList(properties)); } // Ensure that the set is not null Set entries = h.getAuditEntries(); if (entries == null) { entries = new HashSet(); h.setAuditEntries(entries); } AuditEntry entry = new AuditEntry(); entry.setPointInTime(new Date()); entry.setWhat("created"); entries.add(entry); return false; } public void onDelete(Object obj, Serializable id, Object[] newValues, String[] properties, Type[] types) { } public void preFlush(Iterator it) { logger.debug("Pre-Flush"); while (it.hasNext()) { Object obj = it.next(); if (!(obj instanceof Auditable)) { continue; } Auditable h = (Auditable) obj; Set s = new HashSet(); // Record all existing entries Set old = h.getAuditEntries(); if (old == null) { old = new HashSet(); h.setAuditEntries(old); } } } public void postFlush(Iterator it) { } public Boolean isUnsaved(Object arg0) { return null; } public int[] findDirty(Object obj, Serializable id, Object[] newValues, Object[] oldValues, String[] properties, Type[] types) { return null; } public Object instantiate(Class clazz, Serializable id) { return null; } }