Package org.geoserver.hibernate

Source Code of org.geoserver.hibernate.HibPropertyChangeInterceptor

package org.geoserver.hibernate;

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

import org.geoserver.catalog.Catalog;
import org.geoserver.catalog.CatalogInfo;
import org.geoserver.catalog.Info;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.StoreInfo;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.config.LoggingInfo;
import org.geoserver.config.ServiceInfo;
import org.geoserver.platform.GeoServerExtensions;
import org.geotools.util.Utilities;
import org.geotools.util.logging.Logging;
import org.hibernate.EmptyInterceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

/**
* Hibernate interceptor which forwards hibernate events to the catalog.
*
* @author Justin Deoliveira, The Open Planning Project
*
*/
public class HibPropertyChangeInterceptor extends EmptyInterceptor implements ApplicationContextAware {

   
    /**
     * A thread local used to prevent the propagation of the same event over and over which will
     * happen if an event listener makes another query against hibernate
     */
    static ThreadLocal<List> events = new ThreadLocal();
    //TODO: a post request hook to clean up this thread local
   
    private final static Logger LOGGER = Logging.getLogger(HibPropertyChangeInterceptor.class);

    /**
     * spring app context
     */
    ApplicationContext appContext;
   
    /**
     * catalog
     */
    Catalog catalog;
   
    /**
     * config
     */
    GeoServer geoServer;

    public HibPropertyChangeInterceptor() {
       
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.appContext = applicationContext;
    }
   
    protected Catalog catalog() {
        if (catalog == null) {
            synchronized (this) {
                if (catalog == null) {
                    catalog = (Catalog) GeoServerExtensions.bean("catalog", appContext);
                }
            }
        }
        return catalog;
    }

    protected GeoServer geoServer() {
        if (geoServer == null) {
            synchronized (this) {
                if (geoServer == null) {
                    geoServer = GeoServerExtensions.bean(GeoServer.class, appContext);
                }
            }
        }
        return geoServer;
    }
   
    public void afterTransactionCompletion(Transaction tx) {
        if (!tx.wasRolledBack()) {
            //TODO: fire post modified... maybe via thread local?
        }
    }

    @Override
    public boolean onFlushDirty(Object entity, Serializable id, Object[] currentState,
            Object[] previousState, String[] propertyNames, Type[] types) {
       
        List<String> propertyNamesChanged = new ArrayList<String>();
        List<Object> oldValues = new ArrayList<Object>();
        List<Object> newValues = new ArrayList<Object>();

        if (previousState != null) {
            for (int i = 0; i < propertyNames.length; i++) {
                Object oldValue = previousState[i];
                Object newValue = currentState[i];

                if (!Utilities.equals(oldValue, newValue)) {
                    propertyNamesChanged.add(propertyNames[i]);
                    oldValues.add(oldValue);
                    newValues.add(newValue);
                }
            }
        } else {
            for (int i = 0; i < propertyNames.length; i++) {
                propertyNamesChanged.add(propertyNames[i]);
            }
        }
       
        Info info = (Info) entity;
        Event e = new Event(info, propertyNamesChanged);
       
        if (events.get() == null) {
            events.set(new ArrayList());
        }
       
        if (events.get().contains(e)) {
            return false;
        }
       
        events.get().add(e);
        try {
            if (!filterEvent(info, propertyNamesChanged, oldValues, newValues)) {
                if (info instanceof CatalogInfo) {
                    catalog().fireModified((CatalogInfo)info, propertyNamesChanged, oldValues, newValues);   
                }
                else {
                    if (info instanceof GeoServerInfo) {
                        geoServer().fireGlobalModified((GeoServerInfo)info, propertyNamesChanged, oldValues, newValues);
                    }
                    else if (info instanceof LoggingInfo) {
                        geoServer().fireLoggingModified((LoggingInfo)info, propertyNamesChanged, oldValues, newValues);
                    }
                    else if (info instanceof ServiceInfo) {
                        geoServer().fireServiceModified((ServiceInfo)info, propertyNamesChanged, oldValues, newValues);
                    }
                }
            }
        }
        finally {
            events.get().remove(e);
        }
       
        return false;
    }
   
    /*
     * method to filter out situations in which we don;t want to throw an event
     */
    protected boolean filterEvent(
        Info entity, List<String> propertyNamesChanged, List oldValues, List newValues) {
       
        //handle default namespace/workspace changing or default datastore
        if ((entity instanceof WorkspaceInfo || entity instanceof NamespaceInfo || entity instanceof StoreInfo) &&
                propertyNamesChanged.size() == 1 && propertyNamesChanged.contains("default")) {
            return true;
        }
       
        return false;
    }
   
    static class Event {
        Info info;
        List<String> changed;
       
        Event(Info info, List<String> changed) {
            this.info = info;
            this.changed = changed;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((changed == null) ? 0 : changed.hashCode());
            result = prime * result + ((info == null) ? 0 : info.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (getClass() != obj.getClass())
                return false;
            Event other = (Event) obj;
            if (changed == null) {
                if (other.changed != null)
                    return false;
            } else if (!changed.equals(other.changed))
                return false;
            if (info == null) {
                if (other.info != null)
                    return false;
            } else if (!info.equals(other.info))
                return false;
            return true;
        }
       
    }
}
TOP

Related Classes of org.geoserver.hibernate.HibPropertyChangeInterceptor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.