[hibernate-commits] Hibernate SVN: r15142 - in search/trunk/src: test/org/hibernate/search/test/configuration and 1 other directory.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Thu Aug 28 07:36:34 EDT 2008


Author: sannegrinovero
Date: 2008-08-28 07:36:34 -0400 (Thu, 28 Aug 2008)
New Revision: 15142

Added:
   search/trunk/src/test/org/hibernate/search/test/configuration/EventListenerRegisterTest.java
Modified:
   search/trunk/src/java/org/hibernate/search/event/EventListenerRegister.java
   search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java
Log:
HSEARCH-253 : Inconsistent detection of EventListeners during autoregistration

Modified: search/trunk/src/java/org/hibernate/search/event/EventListenerRegister.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/event/EventListenerRegister.java	2008-08-28 07:05:45 UTC (rev 15141)
+++ search/trunk/src/java/org/hibernate/search/event/EventListenerRegister.java	2008-08-28 11:36:34 UTC (rev 15142)
@@ -3,6 +3,7 @@
 
 import java.util.Properties;
 
+import org.hibernate.search.Environment;
 import org.hibernate.event.EventListeners;
 import org.hibernate.event.PostCollectionRecreateEventListener;
 import org.hibernate.event.PostCollectionRemoveEventListener;
@@ -10,7 +11,7 @@
 import org.hibernate.event.PostDeleteEventListener;
 import org.hibernate.event.PostInsertEventListener;
 import org.hibernate.event.PostUpdateEventListener;
-import org.slf4j.Logger;
+
 import org.slf4j.LoggerFactory;
 
 /**
@@ -18,163 +19,126 @@
  * 
  * @author Emmanuel Bernard
  * @author Hardy Ferentschik
+ * @author Sanne Grinovero
  */
 public class EventListenerRegister {
 
-	private static final Logger log = LoggerFactory.getLogger(EventListenerRegister.class);
-
-	@SuppressWarnings("unchecked")
-	public static void enableHibernateSearch(EventListeners eventListeners, Properties properties) {		
-		// check whether search is explicitly enabled - if so there is nothing to do		
-		String enableSearchListeners = properties.getProperty( "hibernate.search.autoregister_listeners" );
-		if("false".equalsIgnoreCase(enableSearchListeners )) {
-			log.info("Property hibernate.search.autoregister_listeners is set to false." +
-					" No attempt will be made to register Hibernate Search event listeners.");
+	/**
+	 * Add the FullTextIndexEventListener to all listeners, if enabled in configuration
+	 * and if not already registered.
+	 * @param listeners
+	 * @param properties the Search configuration
+	 */
+	public static void enableHibernateSearch(EventListeners listeners, Properties properties) {		
+		// check whether search is explicitly disabled - if so there is nothing to do	
+		String enableSearchListeners = properties.getProperty( Environment.AUTOREGISTER_LISTENERS );
+		if ( "false".equalsIgnoreCase( enableSearchListeners ) ) {
+			LoggerFactory.getLogger( EventListenerRegister.class ).info(
+					"Property hibernate.search.autoregister_listeners is set to false." +
+					" No attempt will be made to register Hibernate Search event listeners." );
 			return;
 		}
-				
-		FullTextIndexEventListener searchEventListener = new FullTextIndexEventListener();
+		final FullTextIndexEventListener searchListener = new FullTextIndexEventListener();
+		// PostInsertEventListener
+		listeners.setPostInsertEventListeners(
+			addIfNeeded(
+				listeners.getPostInsertEventListeners(),
+				searchListener,
+				new PostInsertEventListener[] { searchListener } )
+			);
+		// PostUpdateEventListener
+		listeners.setPostUpdateEventListeners(
+			addIfNeeded(
+				listeners.getPostUpdateEventListeners(),
+				searchListener,
+				new PostUpdateEventListener[] { searchListener } )
+			);
+		// PostDeleteEventListener
+		listeners.setPostDeleteEventListeners(
+			addIfNeeded(
+				listeners.getPostDeleteEventListeners(),
+				searchListener,
+				new PostDeleteEventListener[] { searchListener } )
+			);
 		
-		//TODO Generalize this. Pretty much the same code all the time. Reflection? 
-		final Class<? extends FullTextIndexEventListener> searchEventListenerClass = searchEventListener.getClass();
-		{
-			boolean present = false;
-			PostInsertEventListener[] listeners = eventListeners
-					.getPostInsertEventListeners();
-			if (listeners != null) {
-				for (Object eventListener : listeners) {
-					// not isAssignableFrom since the user could subclass
-					present = present
-							|| searchEventListenerClass == eventListener.getClass()
-							|| searchEventListenerClass == eventListener.getClass().getSuperclass(); //for FullTextIndexCollectionEventListener
-				}
-				if (!present) {
-					int length = listeners.length + 1;
-					PostInsertEventListener[] newListeners = new PostInsertEventListener[length];
-					System.arraycopy(listeners, 0, newListeners, 0, length - 1);
-					newListeners[length - 1] = searchEventListener;
-					eventListeners.setPostInsertEventListeners(newListeners);
-				}
-			} else {
-				eventListeners
-						.setPostInsertEventListeners(new PostInsertEventListener[] { searchEventListener });
-			}
+		// PostCollectionRecreateEventListener
+		listeners.setPostCollectionRecreateEventListeners(
+			addIfNeeded(
+				listeners.getPostCollectionRecreateEventListeners(),
+				searchListener,
+				new PostCollectionRecreateEventListener[] { searchListener } )
+			);
+		// PostCollectionRemoveEventListener
+		listeners.setPostCollectionRemoveEventListeners(
+			addIfNeeded(
+				listeners.getPostCollectionRemoveEventListeners(),
+				searchListener,
+				new PostCollectionRemoveEventListener[] { searchListener } )
+			);
+		// PostCollectionUpdateEventListener
+		listeners.setPostCollectionUpdateEventListeners(
+			addIfNeeded(
+				listeners.getPostCollectionUpdateEventListeners(),
+				searchListener,
+				new PostCollectionUpdateEventListener[] { searchListener } )
+			);
+		
+	}
+
+	/**
+	 * Verifies if a Search listener is already present; if not it will return
+	 * a grown address adding the listener to it.
+	 * @param <T> the type of listeners
+	 * @param listeners
+	 * @param searchEventListener
+	 * @param toUseOnNull this is returned if listeners==null
+	 * @return
+	 */
+	private static <T> T[] addIfNeeded(T[] listeners, T searchEventListener, T[] toUseOnNull) {
+		if ( listeners == null ) {
+			return toUseOnNull;
 		}
-		{
-			boolean present = false;
-			PostUpdateEventListener[] listeners = eventListeners
-					.getPostUpdateEventListeners();
-			if (listeners != null) {
-				for (Object eventListener : listeners) {
-					// not isAssignableFrom since the user could subclass
-					present = present
-							|| searchEventListenerClass == eventListener.getClass()
-							|| searchEventListenerClass == eventListener.getClass().getSuperclass(); //for FullTextIndexCollectionEventListener
-				}
-				if (!present) {
-					int length = listeners.length + 1;
-					PostUpdateEventListener[] newListeners = new PostUpdateEventListener[length];
-					System.arraycopy(listeners, 0, newListeners, 0, length - 1);
-					newListeners[length - 1] = searchEventListener;
-					eventListeners.setPostUpdateEventListeners(newListeners);
-				}
-			} else {
-				eventListeners
-						.setPostUpdateEventListeners(new PostUpdateEventListener[] { searchEventListener });
-			}
+		else if ( ! isPresentInListeners( listeners ) ) {
+			return appendToArray( listeners, searchEventListener );
 		}
-		{
-			boolean present = false;
-			PostDeleteEventListener[] listeners = eventListeners
-					.getPostDeleteEventListeners();
-			if (listeners != null) {
-				for (Object eventListener : listeners) {
-					// not isAssignableFrom since the user could subclass
-					present = present
-							|| searchEventListenerClass == eventListener.getClass()
-							|| searchEventListenerClass == eventListener.getClass().getSuperclass(); //for FullTextIndexCollectionEventListener
-				}
-				if (!present) {
-					int length = listeners.length + 1;
-					PostDeleteEventListener[] newListeners = new PostDeleteEventListener[length];
-					System.arraycopy(listeners, 0, newListeners, 0, length - 1);
-					newListeners[length - 1] = searchEventListener;
-					eventListeners.setPostDeleteEventListeners(newListeners);
-				}
-			} else {
-				eventListeners
-						.setPostDeleteEventListeners(new PostDeleteEventListener[] { searchEventListener });
-			}
-		}		
-		{
-			boolean present = false;
-			PostCollectionRecreateEventListener[] listeners = eventListeners.getPostCollectionRecreateEventListeners();
-			if ( listeners != null ) {
-				for (Object eventListener : listeners) {
-					//not isAssignableFrom since the user could subclass
-					present = present
-							|| searchEventListenerClass == eventListener.getClass()
-							|| searchEventListenerClass == eventListener.getClass().getSuperclass(); //for FullTextIndexCollectionEventListener
-				}
-				if ( !present ) {
-					int length = listeners.length + 1;
-					PostCollectionRecreateEventListener[] newListeners = new PostCollectionRecreateEventListener[length];
-					System.arraycopy( listeners, 0, newListeners, 0, length - 1 );
-					newListeners[length - 1] = searchEventListener;
-					eventListeners.setPostCollectionRecreateEventListeners( newListeners );
-				}
-			}
-			else {
-				eventListeners.setPostCollectionRecreateEventListeners(
-						new PostCollectionRecreateEventListener[] { searchEventListener }
-				);
-			}
+		else {
+			return listeners;
 		}
-		{
-			boolean present = false;
-			PostCollectionRemoveEventListener[] listeners = eventListeners.getPostCollectionRemoveEventListeners();
-			if ( listeners != null ) {
-				for (Object eventListener : listeners) {
-					//not isAssignableFrom since the user could subclass
-					present = present
-							|| searchEventListenerClass == eventListener.getClass()
-							|| searchEventListenerClass == eventListener.getClass().getSuperclass(); //for FullTextIndexCollectionEventListener
-				}
-				if ( !present ) {
-					int length = listeners.length + 1;
-					PostCollectionRemoveEventListener[] newListeners = new PostCollectionRemoveEventListener[length];
-					System.arraycopy( listeners, 0, newListeners, 0, length - 1 );
-					newListeners[length - 1] = searchEventListener;
-					eventListeners.setPostCollectionRemoveEventListeners( newListeners );
-				}
+	}
+
+	/**
+	 * Will add one element to the end of an array.
+	 * @param <T> The array type
+	 * @param listeners The original array
+	 * @param newElement The element to be added
+	 * @return A new array containing all listeners and newElement.
+	 */
+	@SuppressWarnings("unchecked")
+	private static <T> T[] appendToArray(T[] listeners, T newElement) {
+		int length = listeners.length;
+		T[] ret = (T[])java.lang.reflect.Array.newInstance(
+				listeners.getClass().getComponentType(), length + 1 );
+		System.arraycopy( listeners, 0, ret, 0, length );
+		ret[length] = newElement;
+		return ret;
+	}
+	
+	/**
+	 * Verifies if a FullTextIndexEventListener is contained in the array.
+	 * @param listeners
+	 * @return true if it is contained in.
+	 */
+	@SuppressWarnings("deprecation")
+	private static boolean isPresentInListeners(Object[] listeners) {
+		for (Object eventListener : listeners) {
+			if ( FullTextIndexEventListener.class == eventListener.getClass() ) {
+				return true;
 			}
-			else {
-				eventListeners.setPostCollectionRemoveEventListeners(
-						new PostCollectionRemoveEventListener[] { searchEventListener }
-				);
+			if ( FullTextIndexCollectionEventListener.class == eventListener.getClass() ) {
+				return true;
 			}
 		}
-		{
-			boolean present = false;
-			PostCollectionUpdateEventListener[] listeners = eventListeners.getPostCollectionUpdateEventListeners();
-			if ( listeners != null ) {
-				for (Object eventListener : listeners) {
-					//not isAssignableFrom since the user could subclass
-					present = present || searchEventListenerClass == eventListener.getClass();
-				}
-				if ( !present ) {
-					int length = listeners.length + 1;
-					PostCollectionUpdateEventListener[] newListeners = new PostCollectionUpdateEventListener[length];
-					System.arraycopy( listeners, 0, newListeners, 0, length - 1 );
-					newListeners[length - 1] = searchEventListener;
-					eventListeners.setPostCollectionUpdateEventListeners( newListeners );
-				}
-			}
-			else {
-				eventListeners.setPostCollectionUpdateEventListeners(
-						new PostCollectionUpdateEventListener[] { searchEventListener }
-				);
-			}
-		}		
+		return false;
 	}
+		
 }

Modified: search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java
===================================================================
--- search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java	2008-08-28 07:05:45 UTC (rev 15141)
+++ search/trunk/src/java/org/hibernate/search/event/FullTextIndexEventListener.java	2008-08-28 11:36:34 UTC (rev 15142)
@@ -39,6 +39,7 @@
  */
 //TODO work on sharing the same indexWriters and readers across a single post operation...
 //TODO implement and use a LockableDirectoryProvider that wraps a DP to handle the lock inside the LDP
+//TODO make this class final as soon as FullTextIndexCollectionEventListener is removed.
 @SuppressWarnings( "serial" )
 public class FullTextIndexEventListener implements PostDeleteEventListener,
 		PostInsertEventListener, PostUpdateEventListener,

Added: search/trunk/src/test/org/hibernate/search/test/configuration/EventListenerRegisterTest.java
===================================================================
--- search/trunk/src/test/org/hibernate/search/test/configuration/EventListenerRegisterTest.java	                        (rev 0)
+++ search/trunk/src/test/org/hibernate/search/test/configuration/EventListenerRegisterTest.java	2008-08-28 11:36:34 UTC (rev 15142)
@@ -0,0 +1,176 @@
+// $Id$
+package org.hibernate.search.test.configuration;
+
+import java.util.Properties;
+
+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.event.PostDeleteEvent;
+import org.hibernate.event.PostDeleteEventListener;
+import org.hibernate.event.PostInsertEvent;
+import org.hibernate.event.PostInsertEventListener;
+import org.hibernate.event.PostUpdateEvent;
+import org.hibernate.event.PostUpdateEventListener;
+import org.hibernate.search.Environment;
+import org.hibernate.search.event.EventListenerRegister;
+import org.hibernate.search.event.FullTextIndexEventListener;
+import org.hibernate.search.event.FullTextIndexCollectionEventListener;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Sanne Grinovero
+ */
+ at SuppressWarnings("deprecation")
+public class EventListenerRegisterTest extends TestCase {
+	
+	public void testRegisterOnEmptyListeners_CfgDisabled() {
+		EventListeners evListeners = new EventListeners();
+		EventListenerRegister.enableHibernateSearch( evListeners, makeConfiguration( false ) );
+		EventListenerRegister.enableHibernateSearch( evListeners, makeConfiguration( false ) );
+		assertPresence( false, evListeners );
+	}
+	
+	public void testRegisterOnEmptyListeners_CfgEnabled() {
+		EventListeners evListeners = new EventListeners();
+		//tests registering multiple times is idempotent:
+		EventListenerRegister.enableHibernateSearch( evListeners, makeConfiguration( true ) );
+		EventListenerRegister.enableHibernateSearch( evListeners, makeConfiguration( true ) );
+		assertPresence( true, evListeners );
+	}
+	
+	public void testRegisterOnEmptyListeners_CfgAuto() {
+		EventListeners evListeners = new EventListeners();
+		EventListenerRegister.enableHibernateSearch( evListeners, new Properties() );
+		EventListenerRegister.enableHibernateSearch( evListeners, new Properties() );
+		assertPresence( true, evListeners );
+	}
+	
+	public void testOnAlreadyRegistered() {
+		helperOnAlreadyRegistered( new FullTextIndexEventListener() );
+	}
+	
+	public void testOnAlreadyRegisteredDeprecated() {
+		helperOnAlreadyRegistered( new FullTextIndexCollectionEventListener() );
+	}
+	
+	public void testOnPopulatedEventListeners() {
+		EventListeners evListeners = makeSomeEventListeners();
+		EventListenerRegister.enableHibernateSearch( evListeners, new Properties() );
+		EventListenerRegister.enableHibernateSearch( evListeners, new Properties() );
+		assertPresence( true, evListeners );
+	}
+	
+	private void helperOnAlreadyRegistered(FullTextIndexEventListener listenerFullText) {
+		
+		AnotherListener listenerA = new AnotherListener();
+		AnotherListener listenerB = new AnotherListener();
+		
+		EventListeners evListeners = new EventListeners();
+		evListeners.setPostInsertEventListeners(
+				new PostInsertEventListener[]{ listenerA, listenerB, listenerFullText }  );
+		evListeners.setPostUpdateEventListeners(
+				new PostUpdateEventListener[]{ listenerA, listenerB, listenerFullText } );
+		evListeners.setPostDeleteEventListeners(
+				new PostDeleteEventListener[]{ listenerA, listenerB, listenerFullText } );
+		evListeners.setPostCollectionRecreateEventListeners(
+				new PostCollectionRecreateEventListener[]{ listenerA, listenerB, listenerFullText } );
+		evListeners.setPostCollectionRemoveEventListeners(
+				new PostCollectionRemoveEventListener[]{ listenerA, listenerB, listenerFullText } );
+		evListeners.setPostCollectionUpdateEventListeners(
+				new PostCollectionUpdateEventListener[]{ listenerA, listenerB, listenerFullText } );
+		
+		EventListenerRegister.enableHibernateSearch( evListeners, makeConfiguration( false ) );
+		EventListenerRegister.enableHibernateSearch( evListeners, makeConfiguration( false ) );
+		EventListenerRegister.enableHibernateSearch( evListeners, makeConfiguration( false ) );
+		assertPresence( true, evListeners );
+	}
+	
+	private EventListeners makeSomeEventListeners() {
+		
+		AnotherListener listenerA = new AnotherListener();
+		AnotherListener listenerB = new AnotherListener();
+		AnotherListener listenerC = new AnotherListener();
+		
+		EventListeners evListeners = new EventListeners();
+		evListeners.setPostInsertEventListeners(
+				new PostInsertEventListener[]{ listenerA, listenerB, listenerC }  );
+		evListeners.setPostUpdateEventListeners(
+				new PostUpdateEventListener[]{ listenerA, listenerB, listenerC } );
+		evListeners.setPostDeleteEventListeners(
+				new PostDeleteEventListener[]{ listenerA, listenerB, listenerC } );
+		evListeners.setPostCollectionRecreateEventListeners(
+				new PostCollectionRecreateEventListener[]{ listenerA, listenerB, listenerC } );
+		evListeners.setPostCollectionRemoveEventListeners(
+				new PostCollectionRemoveEventListener[]{ listenerA, listenerB, listenerC } );
+		evListeners.setPostCollectionUpdateEventListeners(
+				new PostCollectionUpdateEventListener[]{ listenerA, listenerB, listenerC } );
+		
+		return evListeners;
+	}
+	
+	private void assertPresence(boolean expected, EventListeners evListeners) {
+		assertEquals( expected, isPresent( evListeners.getPostInsertEventListeners() ) );
+		assertEquals( expected, isPresent( evListeners.getPostUpdateEventListeners() ) );
+		assertEquals( expected, isPresent( evListeners.getPostDeleteEventListeners() ) );
+		assertEquals( expected, isPresent( evListeners.getPostCollectionRecreateEventListeners() ) );
+		assertEquals( expected, isPresent( evListeners.getPostCollectionRemoveEventListeners() ) );
+		assertEquals( expected, isPresent( evListeners.getPostCollectionUpdateEventListeners() ) );
+	}
+
+	private static Properties makeConfiguration(boolean enableSearch) {
+		Properties p = new Properties();
+		p.setProperty( Environment.AUTOREGISTER_LISTENERS, String.valueOf( enableSearch ) );
+		return p;
+	}
+
+	private static boolean isPresent(Object[] listeners) {
+		if (listeners==null)
+			return false;
+		boolean found = false; // to verify class present at most once.
+		for (Object eventListener : listeners) {
+			if ( FullTextIndexEventListener.class == eventListener.getClass() ) {
+				assertFalse( found );
+				found = true;
+			}
+			if ( FullTextIndexCollectionEventListener.class == eventListener.getClass() ) {
+				assertFalse( found );
+				found = true;
+			}
+		}
+		return found;
+	}
+	
+	private static class AnotherListener implements PostDeleteEventListener,
+	PostInsertEventListener, PostUpdateEventListener,
+	PostCollectionRecreateEventListener, PostCollectionRemoveEventListener,
+	PostCollectionUpdateEventListener {
+		
+		//empty methods: just needing any implementation of these listeners.
+
+		public void onPostDelete(PostDeleteEvent event) {
+		}
+
+		public void onPostInsert(PostInsertEvent event) {
+		}
+
+		public void onPostUpdate(PostUpdateEvent event) {
+		}
+
+		public void onPostRecreateCollection(PostCollectionRecreateEvent event) {
+		}
+
+		public void onPostRemoveCollection(PostCollectionRemoveEvent event) {
+		}
+
+		public void onPostUpdateCollection(PostCollectionUpdateEvent event) {
+		}
+		
+	}
+
+}


Property changes on: search/trunk/src/test/org/hibernate/search/test/configuration/EventListenerRegisterTest.java
___________________________________________________________________
Name: svn:keywords
   + Id




More information about the hibernate-commits mailing list