/* * Copyright 2004-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.compass.gps.device.jpa.lifecycle; import java.io.Serializable; import java.util.ArrayList; import javax.persistence.EntityManagerFactory; import org.compass.gps.device.jpa.JpaGpsDevice; import org.compass.gps.device.jpa.JpaGpsDeviceException; import org.hibernate.ejb.HibernateEntityManagerFactory; import org.hibernate.engine.EntityEntry; import org.hibernate.event.AbstractCollectionEvent; import org.hibernate.event.EventListeners; import org.hibernate.event.PostCollectionRecreateEvent; import org.hibernate.event.PostCollectionRecreateEventListener; import org.hibernate.event.PostCollectionRemoveEvent; import org.hibernate.event.PostCollectionRemoveEventListener; import org.hibernate.event.PostCollectionUpdateEvent; import org.hibernate.event.PostCollectionUpdateEventListener; import org.hibernate.impl.SessionFactoryImpl; /** * @author kimchy */ public class HibernateJpaEntityCollectionLifecycleInjector extends HibernateJpaEntityLifecycleInjector { public static class HibernateCollectionEventListener extends HibernateEventListener implements PostCollectionRecreateEventListener, PostCollectionRemoveEventListener, PostCollectionUpdateEventListener { public HibernateCollectionEventListener(JpaGpsDevice device) { super(device); } public void onPostRecreateCollection(PostCollectionRecreateEvent postCollectionRecreateEvent) { processCollectionEvent(postCollectionRecreateEvent); } public void onPostRemoveCollection(PostCollectionRemoveEvent postCollectionRemoveEvent) { processCollectionEvent(postCollectionRemoveEvent); } public void onPostUpdateCollection(PostCollectionUpdateEvent postCollectionUpdateEvent) { processCollectionEvent(postCollectionUpdateEvent); } private void processCollectionEvent(AbstractCollectionEvent event) { final Object entity = event.getAffectedOwnerOrNull(); if (entity == null) { //Hibernate cannot determine every single time the owner especially incase detached objects are involved // or property-ref is used //Should log really but we don't know if we're interested in this collection for indexing return; } Serializable id = getId(entity, event); if (id == null) { log.warn("Unable to reindex entity on collection change, id cannot be extracted: " + event.getAffectedOwnerEntityName()); return; } postUpdate(entity); } private Serializable getId(Object entity, AbstractCollectionEvent event) { Serializable id = event.getAffectedOwnerIdOrNull(); if (id == null) { //most likely this recovery is unnecessary since Hibernate Core probably try that EntityEntry entityEntry = event.getSession().getPersistenceContext().getEntry(entity); id = entityEntry == null ? null : entityEntry.getId(); } return id; } } private Object eventListener; public HibernateJpaEntityCollectionLifecycleInjector() { super(); } public HibernateJpaEntityCollectionLifecycleInjector(boolean registerPostCommitListeneres) { super(registerPostCommitListeneres); } public void injectLifecycle(EntityManagerFactory entityManagerFactory, JpaGpsDevice device) throws JpaGpsDeviceException { super.injectLifecycle(entityManagerFactory, device); if (registerPostCommitListeneres) { return; } HibernateEntityManagerFactory hibernateEntityManagerFactory = (HibernateEntityManagerFactory) entityManagerFactory; SessionFactoryImpl sessionFactory = (SessionFactoryImpl) hibernateEntityManagerFactory.getSessionFactory(); EventListeners eventListeners = sessionFactory.getEventListeners(); if (eventListener instanceof PostCollectionRecreateEventListener) { PostCollectionRecreateEventListener[] listeners = eventListeners.getPostCollectionRecreateEventListeners(); PostCollectionRecreateEventListener[] tempListeners = new PostCollectionRecreateEventListener[listeners.length + 1]; System.arraycopy(listeners, 0, tempListeners, 0, listeners.length); tempListeners[listeners.length] = (PostCollectionRecreateEventListener) eventListener; eventListeners.setPostCollectionRecreateEventListeners(tempListeners); } if (eventListener instanceof PostCollectionRemoveEventListener) { PostCollectionRemoveEventListener[] listeners = eventListeners.getPostCollectionRemoveEventListeners(); PostCollectionRemoveEventListener[] tempListeners = new PostCollectionRemoveEventListener[listeners.length + 1]; System.arraycopy(listeners, 0, tempListeners, 0, listeners.length); tempListeners[listeners.length] = (PostCollectionRemoveEventListener) eventListener; eventListeners.setPostCollectionRemoveEventListeners(tempListeners); } if (eventListener instanceof PostCollectionUpdateEventListener) { PostCollectionUpdateEventListener[] listeners = eventListeners.getPostCollectionUpdateEventListeners(); PostCollectionUpdateEventListener[] tempListeners = new PostCollectionUpdateEventListener[listeners.length + 1]; System.arraycopy(listeners, 0, tempListeners, 0, listeners.length); tempListeners[listeners.length] = (PostCollectionUpdateEventListener) eventListener; eventListeners.setPostCollectionUpdateEventListeners(tempListeners); } } public void removeLifecycle(EntityManagerFactory entityManagerFactory, JpaGpsDevice device) throws JpaGpsDeviceException { super.removeLifecycle(entityManagerFactory, device); if (registerPostCommitListeneres) { return; } HibernateEntityManagerFactory hibernateEntityManagerFactory = (HibernateEntityManagerFactory) entityManagerFactory; SessionFactoryImpl sessionFactory = (SessionFactoryImpl) hibernateEntityManagerFactory.getSessionFactory(); EventListeners eventListeners = sessionFactory.getEventListeners(); PostCollectionRecreateEventListener[] postCollectionRecreateEventListeners = eventListeners.getPostCollectionRecreateEventListeners(); ArrayList<PostCollectionRecreateEventListener> tempPostCollectionRecreateEventListeners = new ArrayList<PostCollectionRecreateEventListener>(); for (PostCollectionRecreateEventListener postCollectionRecreateEventListener : postCollectionRecreateEventListeners) { if (!(postCollectionRecreateEventListener instanceof HibernateCollectionEventListener)) { tempPostCollectionRecreateEventListeners.add(postCollectionRecreateEventListener); } } eventListeners.setPostCollectionRecreateEventListeners(tempPostCollectionRecreateEventListeners.toArray(new PostCollectionRecreateEventListener[tempPostCollectionRecreateEventListeners.size()])); PostCollectionUpdateEventListener[] postCollectionUpdateEventListeners = eventListeners.getPostCollectionUpdateEventListeners(); ArrayList<PostCollectionUpdateEventListener> tempPostCollectionUpdateEventListeners = new ArrayList<PostCollectionUpdateEventListener>(); for (PostCollectionUpdateEventListener postCollectionUpdateEventListener : postCollectionUpdateEventListeners) { if (!(postCollectionUpdateEventListener instanceof HibernateCollectionEventListener)) { tempPostCollectionUpdateEventListeners.add(postCollectionUpdateEventListener); } } eventListeners.setPostCollectionUpdateEventListeners(tempPostCollectionUpdateEventListeners.toArray(new PostCollectionUpdateEventListener[tempPostCollectionUpdateEventListeners.size()])); PostCollectionRemoveEventListener[] postCollectionRemoveEventListeners = eventListeners.getPostCollectionRemoveEventListeners(); ArrayList<PostCollectionRemoveEventListener> tempPostCollectionRemoveEventListeners = new ArrayList<PostCollectionRemoveEventListener>(); for (PostCollectionRemoveEventListener postCollectionRemoveEventListener : postCollectionRemoveEventListeners) { if (!(postCollectionRemoveEventListener instanceof HibernateCollectionEventListener)) { tempPostCollectionRemoveEventListeners.add(postCollectionRemoveEventListener); } } eventListeners.setPostCollectionRemoveEventListeners(tempPostCollectionRemoveEventListeners.toArray(new PostCollectionRemoveEventListener[tempPostCollectionRemoveEventListeners.size()])); eventListener = null; } protected Object doCreateListener(JpaGpsDevice device) { eventListener = new HibernateCollectionEventListener(device); return eventListener; } }