/* * Hibernate Search, full-text search for your domain model * * License: GNU Lesser General Public License (LGPL), version 2.1 or later * See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>. */ package org.hibernate.search.testsupport.junit; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Properties; import org.hibernate.search.backend.impl.batch.DefaultBatchBackend; import org.hibernate.search.backend.impl.lucene.AbstractWorkspaceImpl; import org.hibernate.search.backend.impl.lucene.WorkspaceHolder; import org.hibernate.search.backend.spi.BatchBackend; import org.hibernate.search.cfg.SearchMapping; import org.hibernate.search.engine.integration.impl.ExtendedSearchIntegrator; import org.hibernate.search.engine.service.spi.Service; import org.hibernate.search.engine.spi.EntityIndexBinding; import org.hibernate.search.exception.SearchException; import org.hibernate.search.indexes.spi.DirectoryBasedIndexManager; import org.hibernate.search.indexes.spi.IndexManager; import org.hibernate.search.spi.SearchIntegrator; import org.hibernate.search.spi.SearchIntegratorBuilder; import org.hibernate.search.testsupport.setup.SearchConfigurationForTest; import org.hibernate.search.testsupport.setup.TestDefaults; import org.junit.Assert; import org.junit.rules.ExternalResource; /** * Testing SearchFactoryHolder. * * <p>Automatically retrieves configuration options from the classpath file "/test-defaults.properties". * * @author Sanne Grinovero * @since 4.1 */ public class SearchFactoryHolder extends ExternalResource { private final SearchMapping buildMappingDefinition; private final Class<?>[] entities; private final Properties configuration; private final Map<Class<? extends Service>,Service> providedServices = new HashMap<>(); private SearchIntegrator[] searchIntegrator; private int numberOfSessionFactories = 1; private boolean idProvidedImplicit = false; private boolean multitenancyEnabled = false; private boolean enableJPAAnnotationsProcessing = false; private DefaultBatchBackend batchBackend; public SearchFactoryHolder(Class<?>... entities) { this( null, entities ); } public SearchFactoryHolder(SearchMapping buildMappingDefinition, Class<?>... entities) { this.buildMappingDefinition = buildMappingDefinition; this.entities = entities; this.configuration = TestDefaults.getProperties(); } public ExtendedSearchIntegrator getSearchFactory() { return searchIntegrator[0].unwrap( ExtendedSearchIntegrator.class ); } @Override protected void before() throws Throwable { searchIntegrator = new SearchIntegrator[numberOfSessionFactories]; for ( int i = 0; i < numberOfSessionFactories; i++ ) { searchIntegrator[i] = createSearchFactory(); } } private SearchIntegrator createSearchFactory() { SearchConfigurationForTest cfg = new SearchConfigurationForTest(); cfg.setProgrammaticMapping( buildMappingDefinition ); for ( Entry<Class<? extends Service>, Service> entry : providedServices.entrySet() ) { cfg.addProvidedService( entry.getKey(), entry.getValue() ); } for ( String key : configuration.stringPropertyNames() ) { cfg.addProperty( key, configuration.getProperty( key ) ); } for ( Class<?> c : entities ) { cfg.addClass( c ); } cfg.setIdProvidedImplicit( idProvidedImplicit ); cfg.setMultitenancyEnabled( multitenancyEnabled ); cfg.setEnableJPAAnnotationsProcessing( enableJPAAnnotationsProcessing ); return new SearchIntegratorBuilder().configuration( cfg ).buildSearchIntegrator(); } @Override protected void after() { if ( searchIntegrator != null ) { for ( SearchIntegrator sf : searchIntegrator ) { sf.close(); } } } public SearchFactoryHolder withProperty(String key, Object value) { Assert.assertNull( "SearchIntegrator already initialized", searchIntegrator ); configuration.put( key, value ); return this; } public SearchFactoryHolder withIdProvidedImplicit(boolean value) { this.idProvidedImplicit = value; return this; } public SearchFactoryHolder withMultitenancyEnabled(boolean value) { this.multitenancyEnabled = value; return this; } public <T extends Service> SearchFactoryHolder withService(Class<T> serviceType, T serviceInstance) { providedServices.put( serviceType, serviceInstance ); return this; } public IndexManager extractIndexManager(Class indexedType) { EntityIndexBinding indexBindingForEntity = getSearchFactory().getIndexBinding( indexedType ); IndexManager indexManager = (IndexManager) indexBindingForEntity.getIndexManagers()[0]; return indexManager; } public AbstractWorkspaceImpl extractWorkspace(Class indexedType) { DirectoryBasedIndexManager indexManager = (DirectoryBasedIndexManager) extractIndexManager( indexedType ); WorkspaceHolder backend = indexManager.getWorkspaceHolder(); return backend.getIndexResources().getWorkspace(); } /** * Allows to construct multiple copies of the SearchFactory. * Each of them will have identical configuration and share the instances of the provided services. * Most other helpers provided by this class will access only the first SearchFactory, unless * they accept a specific index argument. */ public SearchFactoryHolder multipleInstances(int clusterNodes) { if ( clusterNodes < 1 ) { throw new SearchException( "Can not construct less than one node" ); } this.numberOfSessionFactories = clusterNodes; return this; } public BatchBackend getBatchBackend() { if ( batchBackend == null ) { batchBackend = new DefaultBatchBackend( getSearchFactory(), null ); } return batchBackend; } /** * The default for the tests in hibernate-search-engine is to not rely on JPA * specific annotations. These are typically used though when integrating * with Hibernate, so some tests might want to explicitly enable this. */ public SearchFactoryHolder enableJPAAnnotationsProcessing(boolean enableJPAAnnotationsProcessing) { this.enableJPAAnnotationsProcessing = enableJPAAnnotationsProcessing; return this; } }