/**
* Copyright (c) 2000-present Liferay, Inc. All rights reserved.
*
* This library is free software; you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation; either version 2.1 of the License, or (at your option)
* any later version.
*
* This library is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
* FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
* details.
*/
package com.liferay.portal.search.elasticsearch.connection;
import com.liferay.portal.configuration.metatype.bnd.util.ConfigurableUtil;
import com.liferay.portal.kernel.log.Log;
import com.liferay.portal.kernel.log.LogFactoryUtil;
import com.liferay.portal.search.elasticsearch.configuration.ElasticsearchConfiguration;
import com.liferay.portal.search.elasticsearch.index.IndexFactory;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import org.elasticsearch.action.admin.cluster.health.ClusterHealthResponse;
import org.elasticsearch.client.AdminClient;
import org.elasticsearch.client.Client;
import org.elasticsearch.client.ClusterAdminClient;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
/**
* @author Michael C. Han
*/
@Component(
configurationPid = "com.liferay.portal.search.elasticsearch.configuration.ElasticsearchConfiguration",
immediate = true, service = ElasticsearchConnectionManager.class
)
public class ElasticsearchConnectionManager {
public void connect() {
ElasticsearchConnection elasticsearchConnection =
getElasticsearchConnection();
elasticsearchConnection.connect();
}
public AdminClient getAdminClient() {
Client client = getClient();
return client.admin();
}
public Client getClient() {
ElasticsearchConnection elasticsearchConnection =
getElasticsearchConnection();
if (elasticsearchConnection == null) {
throw new ElasticsearchConnectionNotInitializedException();
}
return elasticsearchConnection.getClient();
}
public ClusterAdminClient getClusterAdminClient() {
AdminClient adminClient = getAdminClient();
return adminClient.cluster();
}
public ClusterHealthResponse getClusterHealthResponse(long timeout) {
ElasticsearchConnection elasticsearchConnection =
getElasticsearchConnection();
return elasticsearchConnection.getClusterHealthResponse(timeout);
}
public ElasticsearchConnection getElasticsearchConnection() {
return _elasticsearchConnections.get(_operationMode);
}
public synchronized void registerCompanyId(long companyId) {
_companyIds.put(companyId, companyId);
}
@Reference(
cardinality = ReferenceCardinality.MANDATORY,
target = "(operation.mode=EMBEDDED)",
unbind = "unsetElasticsearchConnection"
)
public void setEmbeddedElasticsearchConnection(
ElasticsearchConnection elasticsearchConnection) {
_elasticsearchConnections.put(
elasticsearchConnection.getOperationMode(),
elasticsearchConnection);
}
@Reference(
cardinality = ReferenceCardinality.MANDATORY,
target = "(operation.mode=REMOTE)",
unbind = "unsetElasticsearchConnection"
)
public void setRemoteElasticsearchConnection(
ElasticsearchConnection elasticsearchConnection) {
_elasticsearchConnections.put(
elasticsearchConnection.getOperationMode(),
elasticsearchConnection);
}
public synchronized void unregisterCompanyId(long companyId) {
_companyIds.remove(companyId);
}
public void unsetElasticsearchConnection(
ElasticsearchConnection elasticsearchConnection) {
_elasticsearchConnections.remove(
elasticsearchConnection.getOperationMode());
elasticsearchConnection.close();
}
@Activate
protected void activate(Map<String, Object> properties) {
_elasticsearchConfiguration = ConfigurableUtil.createConfigurable(
ElasticsearchConfiguration.class, properties);
activate(_elasticsearchConfiguration.operationMode());
}
protected void activate(OperationMode operationMode) {
validate(operationMode);
_operationMode = operationMode;
}
@Modified
protected synchronized void modified(Map<String, Object> properties) {
_elasticsearchConfiguration = ConfigurableUtil.createConfigurable(
ElasticsearchConfiguration.class, properties);
modify(_elasticsearchConfiguration.operationMode());
}
protected synchronized void modify(OperationMode operationMode) {
if (Objects.equals(operationMode, _operationMode)) {
return;
}
validate(operationMode);
ElasticsearchConnection newElasticsearchConnection =
_elasticsearchConnections.get(operationMode);
newElasticsearchConnection.connect();
if (_operationMode != null) {
ElasticsearchConnection oldElasticsearchConnection =
_elasticsearchConnections.get(_operationMode);
try {
oldElasticsearchConnection.close();
}
catch (Exception e) {
_log.error("Unable to close " + oldElasticsearchConnection, e);
}
}
_operationMode = operationMode;
for (Long companyId : _companyIds.values()) {
try {
indexFactory.createIndices(getAdminClient(), companyId);
}
catch (Exception e) {
if (_log.isWarnEnabled()) {
_log.warn(
"Unable to reinitialize index for company " + companyId,
e);
}
}
}
}
protected void validate(OperationMode operationMode) {
if (!_elasticsearchConnections.containsKey(operationMode)) {
throw new MissingOperationModeException(operationMode);
}
}
@Reference(unbind = "-")
protected IndexFactory indexFactory;
private static final Log _log = LogFactoryUtil.getLog(
ElasticsearchConnectionManager.class);
private final Map<Long, Long> _companyIds = new HashMap<>();
private volatile ElasticsearchConfiguration _elasticsearchConfiguration;
private final Map<OperationMode, ElasticsearchConnection>
_elasticsearchConnections = new HashMap<>();
private OperationMode _operationMode;
}