/* * 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.cfg.impl; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import java.util.Properties; import java.util.Set; import org.hibernate.MultiTenancyStrategy; import org.hibernate.annotations.common.reflection.ReflectionManager; import org.hibernate.annotations.common.reflection.java.JavaReflectionManager; import org.hibernate.boot.Metadata; import org.hibernate.boot.spi.MetadataImplementor; import org.hibernate.engine.config.spi.ConfigurationService; import org.hibernate.engine.jndi.spi.JndiService; import org.hibernate.mapping.PersistentClass; import org.hibernate.search.cfg.SearchMapping; import org.hibernate.search.cfg.spi.IdUniquenessResolver; import org.hibernate.search.cfg.spi.SearchConfiguration; import org.hibernate.search.cfg.spi.SearchConfigurationBase; import org.hibernate.search.engine.impl.HibernateStatelessInitializer; import org.hibernate.search.engine.service.beanresolver.spi.BeanResolver; import org.hibernate.search.engine.service.classloading.spi.ClassLoaderService; import org.hibernate.search.engine.service.named.spi.NamedResolver; import org.hibernate.search.engine.service.spi.Service; import org.hibernate.search.hcore.impl.HibernateSessionFactoryService; import org.hibernate.search.spi.InstanceInitializer; /** * Search configuration implementation wrapping an Hibernate Core configuration * * @author Emmanuel Bernard */ public class SearchConfigurationFromHibernateCore extends SearchConfigurationBase implements SearchConfiguration { private final ConfigurationService configurationService; private final ClassLoaderService classLoaderService; private final BeanResolver beanResolver; private final Map<Class<? extends Service>, Object> providedServices; private final Metadata metadata; private final Properties legacyConfigurationProperties;//For compatibility reasons only. Should be removed? See HSEARCH-1890 private final boolean multitenancyEnabled; private ReflectionManager reflectionManager; public SearchConfigurationFromHibernateCore(Metadata metadata, ConfigurationService configurationService, org.hibernate.boot.registry.classloading.spi.ClassLoaderService hibernateOrmClassLoaderService, org.hibernate.search.hcore.spi.BeanResolver hibernateOrmBeanResolver, HibernateSessionFactoryService sessionService, JndiService namingService) { this.metadata = metadata; // hmm, not sure why we throw NullPointerExceptions from these sanity checks // Shouldn't we use AssertionFailure or a log message + SearchException? (HF) if ( configurationService == null ) { throw new NullPointerException( "Configuration is null" ); } this.configurationService = configurationService; if ( hibernateOrmClassLoaderService == null ) { throw new NullPointerException( "ClassLoaderService is null" ); } this.classLoaderService = new DelegatingClassLoaderService( hibernateOrmClassLoaderService ); this.beanResolver = hibernateOrmBeanResolver != null ? new DelegatingBeanResolver( hibernateOrmBeanResolver ) : null; Map<Class<? extends Service>, Object> providedServices = new HashMap<>( 1 ); providedServices.put( IdUniquenessResolver.class, new HibernateCoreIdUniquenessResolver( metadata ) ); providedServices.put( HibernateSessionFactoryService.class, sessionService ); providedServices.put( NamedResolver.class, new DelegatingNamedResolver( namingService ) ); this.providedServices = Collections.unmodifiableMap( providedServices ); this.legacyConfigurationProperties = extractProperties( configurationService ); MultiTenancyStrategy multitenancyStrategy = sessionService.getSessionFactory().getSessionFactoryOptions().getMultiTenancyStrategy(); this.multitenancyEnabled = !MultiTenancyStrategy.NONE.equals( multitenancyStrategy ); } @Override public Iterator<Class<?>> getClassMappings() { return new ClassIterator( metadata.getEntityBindings().iterator() ); } @Override public Class<?> getClassMapping(String entityName) { return metadata.getEntityBinding( entityName ).getMappedClass(); } @Override public String getProperty(String propertyName) { return configurationService.getSetting( propertyName, org.hibernate.engine.config.spi.StandardConverters.STRING ); } @Override public Properties getProperties() { return this.legacyConfigurationProperties; } @Override public ReflectionManager getReflectionManager() { if ( reflectionManager == null ) { if ( metadata instanceof MetadataImplementor ) { reflectionManager = ((MetadataImplementor) metadata).getMetadataBuildingOptions().getReflectionManager(); } if ( reflectionManager == null ) { // Fall back to our own instance of JavaReflectionManager // when metadata is not a MetadataImplementor or // the reflection manager were not created by Hibernate yet. reflectionManager = new JavaReflectionManager(); } } return reflectionManager; } @Override public SearchMapping getProgrammaticMapping() { return null; } @Override public Map<Class<? extends Service>, Object> getProvidedServices() { return providedServices; } @Override public InstanceInitializer getInstanceInitializer() { return HibernateStatelessInitializer.INSTANCE; } @Override public boolean isIndexMetadataComplete() { return true; } @Override public boolean isMultitenancyEnabled() { return multitenancyEnabled; } @Override public ClassLoaderService getClassLoaderService() { return classLoaderService; } @Override public BeanResolver getBeanResolver() { return beanResolver; } private static class ClassIterator implements Iterator<Class<?>> { private Iterator<PersistentClass> hibernatePersistentClassIterator; private Class<?> future; private ClassIterator(Iterator<PersistentClass> hibernatePersistentClassIterator) { this.hibernatePersistentClassIterator = hibernatePersistentClassIterator; } @Override public boolean hasNext() { //we need to read the next non null one. getMappedClass() can return null and should be ignored if ( future != null ) { return true; } do { if ( !hibernatePersistentClassIterator.hasNext() ) { future = null; return false; } final PersistentClass pc = hibernatePersistentClassIterator.next(); future = pc.getMappedClass(); } while ( future == null ); return true; } @Override public Class<?> next() { //run hasNext to init the next element if ( !hasNext() ) { throw new NoSuchElementException(); } Class<?> result = future; future = null; return result; } @Override public void remove() { throw new UnsupportedOperationException( "Cannot modify Hibernate Core metadata" ); } } private static Properties extractProperties(final ConfigurationService configurationService) { Properties props = new Properties(); Set<Map.Entry> entrySet = configurationService.getSettings().entrySet(); for ( Map.Entry entry : entrySet ) { final Object key = entry.getKey(); if ( key instanceof String ) { props.put( key, entry.getValue() ); } } return props; } @Override public boolean isJPAAnnotationsProcessingEnabled() { return true; } }