org.hyperic.hibernate.HypericInterceptorTarget.java Source code

Java tutorial

Introduction

Here is the source code for org.hyperic.hibernate.HypericInterceptorTarget.java

Source

/*                                                                 
 * NOTE: This copyright does *not* cover user programs that use HQ 
 * program services by normal system calls through the application 
 * program interfaces provided as part of the Hyperic Plug-in Development 
 * Kit or the Hyperic Client Development Kit - this is merely considered 
 * normal use of the program, and does *not* fall under the heading of 
 * "derived work". 
 *  
 * Copyright (C) [2004, 2005, 2006], Hyperic, Inc. 
 * This file is part of HQ.         
 *  
 * HQ is free software; you can redistribute it and/or modify 
 * it under the terms version 2 of the GNU General Public License as 
 * published by the Free Software Foundation. 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. 
 *                
 * You should have received a copy of the GNU General Public License 
 * along with this program; if not, write to the Free Software 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 
 * USA. 
 */

package org.hyperic.hibernate;

import java.io.Serializable;
import java.util.Iterator;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.CallbackException;
import org.hibernate.EmptyInterceptor;
import org.hibernate.EntityMode;
import org.hibernate.ObjectNotFoundException;
import org.hibernate.Transaction;
import org.hibernate.type.Type;

/**
 * multi-purpose interceptor for injecting runtime logic,
 *
 * One use case is to set creation and modified time on
 * on save, merge or collection cascades
 */
@SuppressWarnings("serial")
public class HypericInterceptorTarget extends EmptyInterceptor {
    private final Log _log = LogFactory.getLog(HypericInterceptor.class);

    public String onPrepareStatement(String sql) {
        return sql;
    }

    private boolean entHasContainerManagedTimestamp(Object o) {
        return o instanceof ContainerManagedTimestampTrackable;
    }

    public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
            String[] propertyNames, Type[] types) {
        try {
            if (entHasContainerManagedTimestamp(entity)) {
                return updateTimestamp((ContainerManagedTimestampTrackable) entity, currentState, previousState,
                        propertyNames);
            }
        } catch (ObjectNotFoundException e) {
            _log.warn("entity not found: " + e);
            _log.debug(e, e);
        }
        return false;
    }

    public boolean onSave(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        try {
            if (entHasContainerManagedTimestamp(entity)) {
                return updateTimestamp((ContainerManagedTimestampTrackable) entity, state, null, propertyNames);
            }
        } catch (ObjectNotFoundException e) {
            _log.warn("entity not found: " + e);
            _log.debug(e, e);
        }
        return false;
    }

    private boolean updateTimestamp(ContainerManagedTimestampTrackable entity, Object[] curState,
            Object[] prevState, String[] propertyNames) {
        boolean modified = false;
        long ts = System.currentTimeMillis();
        int modifiedIdx = -1;
        int createdIdx = -1;
        int modifiedIdxToCheckMTime = -1;
        for (int i = 0; i < propertyNames.length; i++) {
            if (prevState != null) {
                if (curState[i] == null && prevState[i] != null) {
                    modified = true;
                } else if (curState[i] != null && prevState[i] == null) {
                    modified = true;
                } else if (curState[i] != null && prevState[i] != null && !curState[i].equals(prevState[i])) {
                    modified = true;
                }
            }
            if (("creationTime".equals(propertyNames[i]) || "ctime".equals(propertyNames[i]))
                    && entity.allowContainerManagedCreationTime()) {
                Long ctime = (Long) curState[i];
                if (ctime == null || ctime.longValue() == 0) {
                    createdIdx = i;
                    modified = true;
                }
            } else if ("modifiedTime".equals(propertyNames[i]) || "mtime".equals(propertyNames[i])) {
                if (entity.allowContainerManagedLastModifiedTime()) {
                    modified = true;
                    modifiedIdx = i;
                } else {
                    modifiedIdxToCheckMTime = i;
                }
            }
        }
        if (createdIdx >= 0) {
            curState[createdIdx] = new Long(ts);
        }
        if (modifiedIdx >= 0 && modified) {
            curState[modifiedIdx] = new Long(ts);
        }

        enforceMTimeAtLeastCTime(curState, modifiedIdxToCheckMTime, createdIdx);

        return modified;
    }

    /**
     * The mtime must be at least equal to the ctime. Otherwise, set 
     * the mtime to the ctime. This may be an issue when the mtime is 
     * managed explicitly, but the ctime is managed by the container.
     * 
     * @param curState
     * @param modifiedIdx
     * @param createdIdx
     */
    private void enforceMTimeAtLeastCTime(Object[] curState, int modifiedIdx, int createdIdx) {
        if (createdIdx >= 0 && modifiedIdx >= 0) {
            Long ctime = (Long) curState[createdIdx];
            Long mtime = (Long) curState[modifiedIdx];

            if (ctime != null && mtime != null && mtime.longValue() < ctime.longValue()) {
                curState[modifiedIdx] = ctime;
            }
        }
    }

    public void afterTransactionBegin(Transaction tx) {
        super.afterTransactionBegin(tx);
    }

    public void afterTransactionCompletion(Transaction tx) {
        super.afterTransactionCompletion(tx);
    }

    public void beforeTransactionCompletion(Transaction tx) {
        super.beforeTransactionCompletion(tx);
    }

    public int[] findDirty(Object entity, Serializable id, Object[] currentState, Object[] previousState,
            String[] propertyNames, Type[] types) {
        return super.findDirty(entity, id, currentState, previousState, propertyNames, types);
    }

    public Object getEntity(String entityName, Serializable id) {
        return super.getEntity(entityName, id);
    }

    public String getEntityName(Object object) {
        return super.getEntityName(object);
    }

    public Object instantiate(String entityName, EntityMode entityMode, Serializable id) {
        return super.instantiate(entityName, entityMode, id);
    }

    public Boolean isTransient(Object entity) {
        return super.isTransient(entity);
    }

    public void onCollectionRecreate(Object collection, Serializable key) throws CallbackException {
        super.onCollectionRecreate(collection, key);
    }

    public void onCollectionRemove(Object collection, Serializable key) throws CallbackException {
        super.onCollectionRemove(collection, key);
    }

    public void onCollectionUpdate(Object collection, Serializable key) throws CallbackException {
        super.onCollectionUpdate(collection, key);
    }

    public void onDelete(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        super.onDelete(entity, id, state, propertyNames, types);
    }

    public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) {
        return super.onLoad(entity, id, state, propertyNames, types);
    }

    public void postFlush(Iterator entities) {
        super.postFlush(entities);
    }

    public void preFlush(Iterator entities) {
        super.preFlush(entities);
    }
}