no.abmu.common.hibernate3.AuditInterceptorH3.java Source code

Java tutorial

Introduction

Here is the source code for no.abmu.common.hibernate3.AuditInterceptorH3.java

Source

/*$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;
    }

}