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
+ */
+@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