com.googlecode.hibernate.audit.synchronization.work.AbstractAuditWorkUnit.java Source code

Java tutorial

Introduction

Here is the source code for com.googlecode.hibernate.audit.synchronization.work.AbstractAuditWorkUnit.java

Source

/**
 * Copyright (C) 2009 Krasimir Chobantonov <kchobantonov@yahoo.com>
 * This file is part of Hibernate Audit.
    
 * Hibernate Audit 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 3 of the License, or (at your
 * option) any later version.
 * 
 * Hibernate Audit 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.
 * 
 * You should have received a copy of the GNU General Public License along
 * with Hibernate Audit.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
package com.googlecode.hibernate.audit.synchronization.work;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.transaction.InvalidTransactionException;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.engine.spi.NamedQueryDefinition;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.engine.transaction.jta.platform.spi.JtaPlatform;
import org.hibernate.type.CompositeType;
import org.hibernate.type.EntityType;
import org.hibernate.type.Type;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.googlecode.hibernate.audit.HibernateAudit;
import com.googlecode.hibernate.audit.configuration.AuditConfiguration;
import com.googlecode.hibernate.audit.model.AuditEvent;
import com.googlecode.hibernate.audit.model.AuditLogicalGroup;
import com.googlecode.hibernate.audit.model.clazz.AuditType;
import com.googlecode.hibernate.audit.model.clazz.AuditTypeField;
import com.googlecode.hibernate.audit.model.object.AuditObject;
import com.googlecode.hibernate.audit.model.object.ComponentAuditObject;
import com.googlecode.hibernate.audit.model.property.AuditObjectProperty;
import com.googlecode.hibernate.audit.model.property.ComponentObjectProperty;
import com.googlecode.hibernate.audit.model.property.EntityObjectProperty;
import com.googlecode.hibernate.audit.model.property.SimpleObjectProperty;

public abstract class AbstractAuditWorkUnit implements AuditWorkUnit {
    private static final Logger log = LoggerFactory.getLogger(AbstractAuditWorkUnit.class);

    protected abstract String getEntityName();

    private List<AuditLogicalGroup> auditLogicalGroups = new ArrayList<AuditLogicalGroup>();

    protected void processProperty(Session session, AuditConfiguration auditConfiguration, AuditEvent auditEvent,
            Object object, String propertyName, Object propertyValue, Type propertyType, AuditObject auditObject) {
        if (!auditConfiguration.getExtensionManager().getAuditableInformationProvider().isAuditable(getEntityName(),
                propertyName)) {
            return;
        }
        AuditObjectProperty property = null;

        if (propertyType.isEntityType()) {
            property = processEntityProperty(session, auditConfiguration, object, propertyName, propertyValue,
                    propertyType, auditObject);
        } else if (propertyType.isCollectionType()) {
            // collection will be handled by collection event listeners
        } else if (propertyType.isComponentType()) {
            property = processComponentValue(session, auditConfiguration, auditEvent, auditObject, getEntityName(),
                    object, propertyName, propertyValue, (CompositeType) propertyType);
        } else {
            property = createSimpleValue(session, auditConfiguration, auditObject, getEntityName(), object,
                    propertyName, propertyType, propertyValue);
        }

        if (property != null) {
            AuditType auditType = null;
            if (propertyValue != null) {
                auditType = HibernateAudit.getAuditType(session, propertyValue.getClass().getName());
                if (auditType == null) {
                    // subclass that was not registered in the audit metadata -
                    // use the base class
                    auditType = property.getAuditField().getFieldType();
                }
            }

            property.setAuditType(auditType);
            auditObject.getAuditObjectProperties().add(property);
        }
    }

    protected EntityObjectProperty processEntityProperty(Session session, AuditConfiguration auditConfiguration,
            Object object, String propertyName, Object propertyValue, Type propertyType, AuditObject auditObject) {
        String entityName = ((EntityType) propertyType).getAssociatedEntityName();

        Serializable id = null;
        AuditTypeField auditField = HibernateAudit
                .getAuditField(session,
                        auditConfiguration.getExtensionManager().getAuditableInformationProvider()
                                .getAuditTypeClassName(auditConfiguration.getMetadata(), getEntityName()),
                        propertyName);

        if (propertyValue != null) {
            id = session.getSessionFactory().getClassMetadata(entityName).getIdentifier(propertyValue,
                    (SessionImplementor) session);
        }
        EntityObjectProperty property = new EntityObjectProperty();
        property.setAuditObject(auditObject);
        property.setAuditField(auditField);
        property.setIndex(null);
        property.setTargetEntityId(
                auditConfiguration.getExtensionManager().getPropertyValueConverter().toString(propertyType, id));

        return property;
    }

    protected ComponentObjectProperty processComponentValue(Session session, AuditConfiguration auditConfiguration,
            AuditEvent auditEvent, AuditObject auditObject, String entityName, Object entity, String propertyName,
            Object component, CompositeType componentType) {
        AuditTypeField auditField = HibernateAudit.getAuditField(session,
                auditConfiguration.getExtensionManager().getAuditableInformationProvider()
                        .getAuditTypeClassName(auditConfiguration.getMetadata(), entityName),
                propertyName);

        ComponentObjectProperty property = new ComponentObjectProperty();
        property.setAuditObject(auditObject);
        property.setAuditField(auditField);
        property.setIndex(null);
        if (component != null) {
            property.setAuditType(HibernateAudit.getAuditType(session,
                    auditConfiguration.getExtensionManager().getAuditableInformationProvider()
                            .getAuditTypeClassName(auditConfiguration.getMetadata(), componentType)));
        }

        ComponentAuditObject targetComponentAuditObject = null;

        if (component != null) {
            targetComponentAuditObject = new ComponentAuditObject();
            targetComponentAuditObject.setAuditEvent(auditEvent);
            targetComponentAuditObject.setParentAuditObject(auditObject);
            AuditType auditType = HibernateAudit.getAuditType(session,
                    auditConfiguration.getExtensionManager().getAuditableInformationProvider()
                            .getAuditTypeClassName(auditConfiguration.getMetadata(), componentType));
            targetComponentAuditObject.setAuditType(auditType);

            for (int i = 0; i < componentType.getPropertyNames().length; i++) {
                String componentPropertyName = componentType.getPropertyNames()[i];

                Type componentPropertyType = componentType.getSubtypes()[i];
                Object componentPropertyValue = componentType.getPropertyValue(component, i,
                        (SessionImplementor) session);

                processProperty(session, auditConfiguration, auditEvent, component, componentPropertyName,
                        componentPropertyValue, componentPropertyType, targetComponentAuditObject);
            }
        }
        property.setTargetComponentAuditObject(targetComponentAuditObject);

        return property;
    }

    protected SimpleObjectProperty createSimpleValue(Session session, AuditConfiguration auditConfiguration,
            AuditObject auditObject, String entityName, Object entity, String propertyName, Type propertyType,
            Object propertyValue) {
        AuditTypeField auditField = HibernateAudit.getAuditField(session,
                auditConfiguration.getExtensionManager().getAuditableInformationProvider()
                        .getAuditTypeClassName(auditConfiguration.getMetadata(), entityName),
                propertyName);

        SimpleObjectProperty property = new SimpleObjectProperty();
        property.setAuditObject(auditObject);
        property.setAuditField(auditField);
        property.setIndex(null);
        property.setValue(auditConfiguration.getExtensionManager().getPropertyValueConverter()
                .toString(propertyType, propertyValue));

        return property;
    }

    public List<AuditLogicalGroup> getAuditLogicalGroups() {
        return auditLogicalGroups;
    }

    protected AuditLogicalGroup getAuditLogicalGroup(Session session, AuditConfiguration auditConfiguration,
            AuditEvent auditEvent) {

        AuditLogicalGroup logicalGroup = auditConfiguration.getExtensionManager().getAuditLogicalGroupProvider()
                .getAuditLogicalGroup(session, auditEvent);

        AuditLogicalGroup result = null;

        if (logicalGroup != null) {
            AuditType auditType = HibernateAudit.getAuditType(session, logicalGroup.getAuditType().getClassName());
            String externalId = logicalGroup.getExternalId();

            result = HibernateAudit.getAuditLogicalGroup(session, auditType, externalId);

            HibernateException createAuditLogicalGroupException = null;
            if (result == null) {
                createAuditLogicalGroupException = createAuditLogicalGroup(session, logicalGroup, auditType);
                // remove the cached query (possibly null) results so that the result after that is not null. 
                NamedQueryDefinition namedQueryDefinition = ((SessionFactoryImplementor) session
                        .getSessionFactory()).getNamedQuery(
                                HibernateAudit.SELECT_AUDIT_LOCAL_GROUP_BY_AUDIT_TYPE_AND_EXTERNAL_ID);
                if (namedQueryDefinition.isCacheable()) {
                    String cacheRegion = ((SessionFactoryImplementor) session.getSessionFactory())
                            .getNamedQuery(HibernateAudit.SELECT_AUDIT_LOCAL_GROUP_BY_AUDIT_TYPE_AND_EXTERNAL_ID)
                            .getCacheRegion();
                    if (cacheRegion != null) {
                        session.getSessionFactory().getCache().evictQueryRegion(cacheRegion);
                    } else {
                        session.getSessionFactory().getCache().evictQueryRegions();
                    }
                }

                result = HibernateAudit.getAuditLogicalGroup(session, auditType, externalId);

            }
            if (result == null) {
                if (createAuditLogicalGroupException != null) {
                    throw createAuditLogicalGroupException;
                } else {
                    throw new HibernateException("Unable to create and then retrieve AuditLogicalGroup: className="
                            + logicalGroup.getAuditType().getClassName() + ",externalId="
                            + logicalGroup.getExternalId());
                }
            }
            auditLogicalGroups.add(result);
        }

        return result;
    }

    private HibernateException createAuditLogicalGroup(Session session, AuditLogicalGroup logicalGroup,
            AuditType auditType) {
        Session newSession = null;

        TransactionManager txManager = null;
        javax.transaction.Transaction suspendedTransaction = null;

        try {
            JtaPlatform jtaPlatform = ((SessionFactoryImplementor) session.getSessionFactory()).getSettings()
                    .getJtaPlatform();
            if (jtaPlatform != null) {
                txManager = jtaPlatform.retrieveTransactionManager();
            }

            if (txManager != null) {
                try {
                    suspendedTransaction = txManager.suspend();
                } catch (SystemException e) {
                    throw new HibernateException(e);
                }
            }
            Transaction tx = null;
            try {
                newSession = session.getSessionFactory().openSession();
                tx = newSession.beginTransaction();
                logicalGroup.setAuditType(auditType);
                // when we are creating the audit logical group for the first time we set it to 0, this is before even we may have transaction record - this is executed in separate transaction
                logicalGroup.setLastUpdatedAuditTransactionId(Long.valueOf(0));
                newSession.save(logicalGroup);
                tx.commit();

                return null;
            } catch (HibernateException e) {
                if (log.isDebugEnabled()) {
                    // log the exception is debug level because this most likely
                    // will indicate that there was a concurrent insert and we
                    // are prepared to handle such calls. If this is not the
                    // case and we want to troubleshoot where is the problem
                    // then at least log the exception is DEBUG level so we can
                    // see it.
                    log.debug(
                            "HibernateException occured while creating a new AuditLogicalGroup in new transaction",
                            e);
                }
                if (tx != null) {
                    try {
                        tx.rollback();
                    } catch (HibernateException ignored) {
                    }
                }

                return e;
            } finally {
                if (newSession != null && newSession.isOpen()) {
                    try {
                        newSession.close();
                    } catch (HibernateException ignored) {
                    }
                }
            }
        } finally {
            if (txManager != null && suspendedTransaction != null) {
                try {
                    txManager.resume(suspendedTransaction);
                } catch (SystemException e) {
                    throw new HibernateException(e);
                } catch (InvalidTransactionException e) {
                    throw new HibernateException(e);
                }
            }
        }
    }

}