org.hibernate.search.backend.elasticsearch.impl.ElasticsearchLinkImpl Maven / Gradle / Ivy
/*
 * 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 .
 */
package org.hibernate.search.backend.elasticsearch.impl;
import com.google.gson.GsonBuilder;
import org.hibernate.search.backend.elasticsearch.ElasticsearchVersion;
import org.hibernate.search.backend.elasticsearch.cfg.ElasticsearchBackendSettings;
import org.hibernate.search.backend.elasticsearch.client.impl.ElasticsearchClientUtils;
import org.hibernate.search.backend.elasticsearch.client.spi.ElasticsearchClient;
import org.hibernate.search.backend.elasticsearch.client.spi.ElasticsearchClientFactory;
import org.hibernate.search.backend.elasticsearch.client.spi.ElasticsearchClientImplementor;
import org.hibernate.search.backend.elasticsearch.dialect.impl.ElasticsearchDialectFactory;
import org.hibernate.search.backend.elasticsearch.dialect.protocol.impl.ElasticsearchProtocolDialect;
import org.hibernate.search.backend.elasticsearch.gson.spi.GsonProvider;
import org.hibernate.search.backend.elasticsearch.link.impl.ElasticsearchLink;
import org.hibernate.search.backend.elasticsearch.logging.impl.Log;
import org.hibernate.search.backend.elasticsearch.lowlevel.syntax.metadata.impl.ElasticsearchIndexMetadataSyntax;
import org.hibernate.search.backend.elasticsearch.lowlevel.syntax.search.impl.ElasticsearchSearchSyntax;
import org.hibernate.search.backend.elasticsearch.resources.impl.BackendThreads;
import org.hibernate.search.backend.elasticsearch.search.query.impl.ElasticsearchSearchResultExtractorFactory;
import org.hibernate.search.backend.elasticsearch.work.builder.factory.impl.ElasticsearchWorkBuilderFactory;
import org.hibernate.search.engine.cfg.spi.ConfigurationProperty;
import org.hibernate.search.engine.cfg.spi.ConfigurationPropertySource;
import org.hibernate.search.engine.environment.bean.BeanHolder;
import org.hibernate.search.util.common.AssertionFailure;
import org.hibernate.search.util.common.impl.Closer;
import org.hibernate.search.util.common.logging.impl.LoggerFactory;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Optional;
class ElasticsearchLinkImpl implements ElasticsearchLink {
	private static final Log log = LoggerFactory.make( Log.class, MethodHandles.lookup() );
	private static final ConfigurationProperty SCROLL_TIMEOUT =
			ConfigurationProperty.forKey( ElasticsearchBackendSettings.SCROLL_TIMEOUT )
					.asInteger()
					.withDefault( ElasticsearchBackendSettings.Defaults.SCROLL_TIMEOUT )
					.build();
	private final BeanHolder extends ElasticsearchClientFactory> clientFactoryHolder;
	private final BackendThreads threads;
	private final GsonProvider defaultGsonProvider;
	private final boolean logPrettyPrinting;
	private final ElasticsearchDialectFactory dialectFactory;
	private final Optional configuredVersionOptional;
	private final boolean versionCheckEnabled;
	private ElasticsearchClientImplementor clientImplementor;
	private ElasticsearchVersion elasticsearchVersion;
	private GsonProvider gsonProvider;
	private ElasticsearchIndexMetadataSyntax indexMetadataSyntax;
	private ElasticsearchSearchSyntax searchSyntax;
	private ElasticsearchWorkBuilderFactory workBuilderFactory;
	private ElasticsearchSearchResultExtractorFactory searchResultExtractorFactory;
	private Integer scrollTimeout;
	ElasticsearchLinkImpl(BeanHolder extends ElasticsearchClientFactory> clientFactoryHolder,
			BackendThreads threads, GsonProvider defaultGsonProvider, boolean logPrettyPrinting,
			ElasticsearchDialectFactory dialectFactory,
			Optional configuredVersionOptional,
			boolean versionCheckEnabled) {
		this.clientFactoryHolder = clientFactoryHolder;
		this.threads = threads;
		this.defaultGsonProvider = defaultGsonProvider;
		this.logPrettyPrinting = logPrettyPrinting;
		this.dialectFactory = dialectFactory;
		this.configuredVersionOptional = configuredVersionOptional;
		this.versionCheckEnabled = versionCheckEnabled;
	}
	@Override
	public ElasticsearchClient getClient() {
		checkStarted();
		return clientImplementor;
	}
	@Override
	public GsonProvider getGsonProvider() {
		checkStarted();
		return gsonProvider;
	}
	@Override
	public ElasticsearchIndexMetadataSyntax getIndexMetadataSyntax() {
		checkStarted();
		return indexMetadataSyntax;
	}
	@Override
	public ElasticsearchSearchSyntax getSearchSyntax() {
		checkStarted();
		return searchSyntax;
	}
	@Override
	public ElasticsearchWorkBuilderFactory getWorkBuilderFactory() {
		checkStarted();
		return workBuilderFactory;
	}
	@Override
	public ElasticsearchSearchResultExtractorFactory getSearchResultExtractorFactory() {
		checkStarted();
		return searchResultExtractorFactory;
	}
	@Override
	public Integer getScrollTimeout() {
		checkStarted();
		return scrollTimeout;
	}
	ElasticsearchVersion getElasticsearchVersion() {
		checkStarted();
		return elasticsearchVersion;
	}
	void onStart(ConfigurationPropertySource propertySource) {
		if ( clientImplementor == null ) {
			clientImplementor = clientFactoryHolder.get().create(
					propertySource, threads.getThreadProvider(), threads.getPrefix(),
					threads.getWorkExecutor(), defaultGsonProvider
			);
			clientFactoryHolder.close(); // We won't need it anymore
			if ( versionCheckEnabled ) {
				elasticsearchVersion = ElasticsearchClientUtils.getElasticsearchVersion( clientImplementor );
				if ( configuredVersionOptional.isPresent() ) {
					ElasticsearchVersion configuredVersion = configuredVersionOptional.get();
					if ( !configuredVersion.matches( elasticsearchVersion ) ) {
						throw log.unexpectedElasticsearchVersion( configuredVersion, elasticsearchVersion );
					}
				}
			}
			else {
				configuredVersionOptional.ifPresent( version -> elasticsearchVersion = version );
			}
			ElasticsearchProtocolDialect protocolDialect = dialectFactory.createProtocolDialect( elasticsearchVersion );
			gsonProvider = GsonProvider.create( GsonBuilder::new, logPrettyPrinting );
			indexMetadataSyntax = protocolDialect.createIndexMetadataSyntax();
			searchSyntax = protocolDialect.createSearchSyntax();
			workBuilderFactory = protocolDialect.createWorkBuilderFactory( gsonProvider );
			searchResultExtractorFactory = protocolDialect.createSearchResultExtractorFactory();
			scrollTimeout = SCROLL_TIMEOUT.get( propertySource );
		}
	}
	void onStop() throws IOException {
		try ( Closer closer = new Closer<>() ) {
			closer.push( BeanHolder::close, clientFactoryHolder ); // Just in case start() was not called
			closer.push( ElasticsearchClientImplementor::close, clientImplementor );
		}
	}
	private void checkStarted() {
		if ( clientImplementor == null ) {
			throw new AssertionFailure(
					"Attempt to retrieve Elasticsearch client or related information before the backend was started."
							+ "There is probably a bug in Hibernate Search, please report it."
			);
		}
	}
}
         © 2015 - 2025 Weber Informatics LLC | Privacy Policy