Author: epbernard
Date: 2006-07-01 11:11:45 -0400 (Sat, 01 Jul 2006)
New Revision: 10076
Added:
trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/
trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/DirectoryProvider.java
trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/DirectoryProviderFactory.java
trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/FSDirectoryProvider.java
trunk/HibernateExt/metadata/src/test/org/hibernate/lucene/test/
Modified:
trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java
trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/event/LuceneEventListener.java
Log:
ANN-385 abstract lucene directory.
Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java 2006-07-01 12:50:34 UTC (rev 10075)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/DocumentBuilder.java 2006-07-01 15:11:45 UTC (rev 10076)
@@ -4,10 +4,10 @@
import java.beans.Introspector;
import java.io.Serializable;
import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
-import java.lang.reflect.AnnotatedElement;
import java.util.ArrayList;
import java.util.List;
@@ -15,10 +15,10 @@
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.Term;
-import org.apache.lucene.store.Directory;
import org.hibernate.AssertionFailure;
import org.hibernate.HibernateException;
import org.hibernate.cfg.annotations.Version;
+import org.hibernate.lucene.store.DirectoryProvider;
//TODO handle attribute (only getters are handled currently)
public class DocumentBuilder<T> {
@@ -35,15 +35,15 @@
private final List<String> textNames = new ArrayList<String>();
//private final Class<T> beanClass;
- private final Directory directory;
+ private final DirectoryProvider directoryProvider;
private String idKeywordName;
private final Analyzer analyzer;
private Float idBoost;
- public DocumentBuilder(Class<?> clazz, Analyzer analyzer, Directory directory) {
+ public DocumentBuilder(Class<?> clazz, Analyzer analyzer, DirectoryProvider directory) {
//this.beanClass = clazz;
this.analyzer = analyzer;
- this.directory = directory;
+ this.directoryProvider = directory;
for ( Class currClass = clazz; currClass != null ; currClass = currClass.getSuperclass() ) {
Method[] methods = currClass.getDeclaredMethods();
@@ -174,8 +174,8 @@
return Introspector.decapitalize( methodName.substring( startIndex ) );
}
- public Directory getDirectory() {
- return directory;
+ public DirectoryProvider getDirectoryProvider() {
+ return directoryProvider;
}
public Analyzer getAnalyzer() {
Modified: trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/event/LuceneEventListener.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/event/LuceneEventListener.java 2006-07-01 12:50:34 UTC (rev 10075)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/event/LuceneEventListener.java 2006-07-01 15:11:45 UTC (rev 10076)
@@ -1,7 +1,6 @@
//$Id$
package org.hibernate.lucene.event;
-import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.HashMap;
@@ -18,8 +17,6 @@
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.Term;
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.FSDirectory;
import org.hibernate.HibernateException;
import org.hibernate.cfg.Configuration;
import org.hibernate.event.Initializable;
@@ -32,6 +29,8 @@
import org.hibernate.lucene.DocumentBuilder;
import org.hibernate.lucene.Environment;
import org.hibernate.lucene.Indexed;
+import org.hibernate.lucene.store.DirectoryProvider;
+import org.hibernate.lucene.store.DirectoryProviderFactory;
import org.hibernate.mapping.PersistentClass;
/**
@@ -48,7 +47,7 @@
private Map<Class, DocumentBuilder<Object>> documentBuilders = new HashMap<Class, DocumentBuilder<Object>>();
//** keep track of the index modifiers per file since 1 index modifier can be present at a time */
- private Map<Directory, Lock> indexLock = new HashMap<Directory, Lock>();
+ private Map<DirectoryProvider, Lock> indexLock = new HashMap<DirectoryProvider, Lock>();
private boolean initialized;
private static final Log log = LogFactory.getLog( LuceneEventListener.class );
@@ -81,63 +80,27 @@
throw new HibernateException( "Failed to instantiate lucene analyzer with type " + analyzerClassName );
}
- // Initialize index parent dir
- String indexDirName = cfg.getProperty( Environment.INDEX_BASE_DIR );
- File indexDir = indexDirName != null ? new File( indexDirName ) : new File( "." );
-
- if ( !( indexDir.exists() && indexDir.isDirectory() ) ) {
- //TODO create the directory
- throw new HibernateException( "Index directory does not exists: " + Environment.INDEX_BASE_DIR );
- }
- if ( !indexDir.canWrite() ) {
- throw new HibernateException( "Cannot write into index directory: " + Environment.INDEX_BASE_DIR );
- }
- log.info( "Setting index dir to " + indexDir );
-
Iterator iter = cfg.getClassMappings();
+ DirectoryProviderFactory factory = new DirectoryProviderFactory();
while ( iter.hasNext() ) {
PersistentClass clazz = (PersistentClass) iter.next();
Class<?> mappedClass = clazz.getMappedClass();
if ( mappedClass != null ) {
if ( mappedClass.isAnnotationPresent( Indexed.class ) ) {
- Indexed indexed = mappedClass.getAnnotation( Indexed.class );
- String fileName = getTypeName( mappedClass, indexed.index() );
- File file = new File( indexDir, fileName );
- Directory directory;
- try {
- boolean create = !file.exists();
- directory = FSDirectory.getDirectory( file.getCanonicalPath(), create );
- if (create) {
- IndexWriter iw = new IndexWriter(directory, new StandardAnalyzer(), create );
- iw.close();
- }
+ DirectoryProvider provider = factory.createDirectoryProvider( mappedClass, cfg );
+ final DocumentBuilder<Object> documentBuilder = new DocumentBuilder<Object>(
+ mappedClass, analyzer, provider
+ );
+ if ( ! indexLock.containsKey( provider ) ) {
+ indexLock.put( provider, new ReentrantLock() );
}
- catch (IOException ie) {
- throw new HibernateException("Unable to initialize index: " + indexed.index(), ie );
- }
- final DocumentBuilder<Object> documentBuilder = new DocumentBuilder<Object>( mappedClass, analyzer, directory );
- if ( ! indexLock.containsKey( directory ) ) {
- indexLock.put( directory, new ReentrantLock() );
- }
documentBuilders.put( mappedClass, documentBuilder );
-// try {
-// IndexWriter iw = new IndexWriter( documentBuilder.getFile(), new StopAnalyzer(), true );
-// iw.close();
-// }
-// catch (IOException ioe) {
-// throw new HibernateException(ioe);
-// }
- log.info( "index file: " + file.getAbsolutePath() );
}
}
}
initialized = true;
}
- private static String getTypeName(Class clazz, String name) {
- return "".equals( name ) ? clazz.getName() : name;
- }
-
public void onPostDelete(PostDeleteEvent event) {
DocumentBuilder builder = documentBuilders.get( event.getEntity().getClass() );
if ( builder != null ) {
@@ -166,12 +129,12 @@
private void remove(DocumentBuilder<?> builder, Serializable id) {
Term term = builder.getTerm( id );
log.debug( "removing: " + term );
- Directory directory = builder.getDirectory();
- Lock lock = indexLock.get( directory );
+ DirectoryProvider directoryProvider = builder.getDirectoryProvider();
+ Lock lock = indexLock.get( directoryProvider );
lock.lock();
try {
- IndexReader reader = IndexReader.open( directory );
+ IndexReader reader = IndexReader.open( directoryProvider.getDirectory() );
reader.deleteDocuments( term );
reader.close();
}
@@ -185,14 +148,16 @@
private void add(final Object entity, final DocumentBuilder<Object> builder, final Serializable id) {
Document doc = builder.getDocument( entity, id );
- if( log.isDebugEnabled() ) {
+ if ( log.isDebugEnabled() ) {
log.debug( "adding: " + doc );
}
- Directory directory = builder.getDirectory();
- Lock lock = indexLock.get( directory );
+ DirectoryProvider directoryProvider = builder.getDirectoryProvider();
+ Lock lock = indexLock.get( directoryProvider );
lock.lock();
try {
- IndexWriter writer = new IndexWriter( directory, builder.getAnalyzer(), false); //have been created at init time
+ IndexWriter writer = new IndexWriter(
+ directoryProvider.getDirectory(), builder.getAnalyzer(), false
+ ); //have been created at init time
writer.addDocument( doc );
writer.close();
}
Added: trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/DirectoryProvider.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/DirectoryProvider.java 2006-07-01 12:50:34 UTC (rev 10075)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/DirectoryProvider.java 2006-07-01 15:11:45 UTC (rev 10076)
@@ -0,0 +1,23 @@
+//$Id: $
+package org.hibernate.lucene.store;
+
+import java.util.Properties;
+
+import org.hibernate.cfg.Configuration;
+import org.apache.lucene.store.Directory;
+
+
+/**
+ * Set up and provide a Lucene <code>Directory</code>
+ * <code>equals()</code> and <code>hashCode()</code> must guaranty to
+ * return true for a provider pointing to the same underlying Lucene Store
+ * This class must be thread safe regarding <code>getDirectory()</code>
+ * @author Emmanuel Bernard
+ */
+public interface DirectoryProvider<TDirectory extends Directory> {
+ /** get the information toi initialize the directory and build its hashCode */
+ void initialize(Class<?> entity, Configuration cfg, Properties properties);
+
+ TDirectory getDirectory();
+}
+
Added: trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/DirectoryProviderFactory.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/DirectoryProviderFactory.java 2006-07-01 12:50:34 UTC (rev 10075)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/DirectoryProviderFactory.java 2006-07-01 15:11:45 UTC (rev 10076)
@@ -0,0 +1,86 @@
+//$Id: $
+package org.hibernate.lucene.store;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.hibernate.HibernateException;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.lucene.Indexed;
+import org.hibernate.util.ReflectHelper;
+import org.hibernate.util.StringHelper;
+
+/**
+ * Create a Lucene directory provider
+ * <p/>
+ * Lucene directory providers are configured through...
+ * hibernate.lucene.default.impl=FSDirectory
+ * hibernate.lucene.toto.impl=FSDirectory
+ * hibernate.lucene.toto.*=
+ *
+ * @author Emmanuel Bernard
+ */
+public class DirectoryProviderFactory {
+ public List<DirectoryProvider> providers = new ArrayList<DirectoryProvider>();
+ private static String LUCENE_PREFIX = "hibernate.lucene.";
+ private static String LUCENE_DEFAULT = LUCENE_PREFIX + "default.";
+ private static String DEFAULT_DIRECTORY_PROVIDER = FSDirectoryProvider.class.getName();
+
+
+
+ public DirectoryProvider createDirectoryProvider(Class<?> entity, Configuration cfg) {
+ //get properties
+ Properties indexProps = getDirectoryProperties( cfg, entity );
+
+ //set up the directory
+ String className = indexProps.getProperty( "impl" );
+ if ( StringHelper.isEmpty( className ) ) {
+ className = DEFAULT_DIRECTORY_PROVIDER;
+ }
+ DirectoryProvider provider = null;
+ try {
+ Class<DirectoryProvider> directoryClass = ReflectHelper.classForName(
+ className, DirectoryProviderFactory.class
+ );
+ provider = directoryClass.newInstance();
+ }
+ catch (Exception e) {
+ throw new HibernateException( "Unable to instanciate directory provider: " + className );
+ }
+ provider.initialize( entity, cfg, indexProps );
+ int index = providers.indexOf( provider );
+ if ( index != -1 ) {
+ //share the same Directory provider for the same underlying store
+ return providers.get( index );
+ }
+ else {
+ providers.add( provider );
+ return provider;
+ }
+ }
+
+ private static Properties getDirectoryProperties(Configuration cfg, Class<?> entity) {
+ Properties props = cfg.getProperties();
+ String indexName = LUCENE_PREFIX + getTypeName( entity );
+ Properties indexProps = new Properties();
+ Properties indexSpecificProps = new Properties();
+ for ( Map.Entry<String, ?> entry : ( (Map<String, ?>) props ).entrySet() ) {
+ String key = entry.getKey();
+ if ( key.startsWith( LUCENE_DEFAULT ) ) {
+ indexProps.setProperty( key.substring( LUCENE_DEFAULT.length() ), (String) entry.getValue() );
+ }
+ else if ( key.startsWith( indexName ) ) {
+ indexSpecificProps.setProperty( key.substring( indexName.length() ), (String) entry.getValue() );
+ }
+ }
+ indexProps.putAll( indexSpecificProps );
+ return indexProps;
+ }
+
+ public static String getTypeName(Class<?> clazz) {
+ String name = clazz.getAnnotation(Indexed.class).index();
+ return "".equals( name ) ? clazz.getName() : name;
+ }
+}
Added: trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/FSDirectoryProvider.java
===================================================================
--- trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/FSDirectoryProvider.java 2006-07-01 12:50:34 UTC (rev 10075)
+++ trunk/HibernateExt/metadata/src/java/org/hibernate/lucene/store/FSDirectoryProvider.java 2006-07-01 15:11:45 UTC (rev 10076)
@@ -0,0 +1,61 @@
+//$Id: $
+package org.hibernate.lucene.store;
+
+import java.io.File;
+import java.io.IOException;
+import java.text.MessageFormat;
+import java.util.Properties;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.FSDirectory;
+import org.apache.lucene.index.IndexWriter;
+import org.apache.lucene.analysis.standard.StandardAnalyzer;
+import org.hibernate.HibernateException;
+import org.hibernate.cfg.Configuration;
+
+/**
+ * Use a Lucene FSDirectory
+ * The base directory is represented by hibernate.lucene.<index>.indexBase
+ * The index is created in <base directory>/<index name>
+ * @author Emmanuel Bernard
+ */
+public class FSDirectoryProvider implements DirectoryProvider {
+ private FSDirectory directory;
+ private static Log log = LogFactory.getLog( FSDirectoryProvider.class );
+
+ public void initialize(Class entity, Configuration cfg, Properties properties) {
+ String indexBase = properties.getProperty( "indexBase", "." );
+ File indexDir = new File( indexBase );
+
+ if ( !( indexDir.exists() && indexDir.isDirectory() ) ) {
+ //TODO create the directory?
+ throw new HibernateException( MessageFormat.format( "Index directory does not exists: {0}", indexBase ) );
+ }
+ if ( !indexDir.canWrite() ) {
+ throw new HibernateException( "Cannot write into index directory: " + indexBase );
+ }
+ log.info( "Setting index dir to " + indexDir );
+
+ String fileName = DirectoryProviderFactory.getTypeName( entity );
+ File file = new File( indexDir, fileName );
+
+ try {
+ boolean create = !file.exists();
+ directory = FSDirectory.getDirectory( file.getCanonicalPath(), create );
+ if (create) {
+ IndexWriter iw = new IndexWriter(directory, new StandardAnalyzer(), create );
+ iw.close();
+ }
+ }
+ catch (IOException e) {
+ throw new HibernateException( "Unable to initialize index: " + fileName, e );
+ }
+
+ }
+
+ public Directory getDirectory() {
+ return directory;
+ }
+}
|