package org.stagemonitor.configuration.source; import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.stagemonitor.core.elasticsearch.ElasticsearchClient; import org.stagemonitor.core.util.JsonUtils; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.ANY; import static com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility.NONE; public class ElasticsearchConfigurationSource extends AbstractConfigurationSource { private final Logger logger = LoggerFactory.getLogger(getClass()); private final String path; private final ElasticsearchClient elasticsearchClient; private final String configurationId; private ConcurrentMap<String, String> configuration = new ConcurrentHashMap<String, String>(); public ElasticsearchConfigurationSource(ElasticsearchClient elasticsearchClient, String configurationId) { this.elasticsearchClient = elasticsearchClient; this.configurationId = configurationId; this.path = "/stagemonitor/configuration-v2/" + this.configurationId; try { reload(); } catch (IOException e) { logger.warn(e.getMessage(), e); } } @Override public String getValue(String key) { return configuration.get(key); } @Override public String getName() { return "Elasticsearch (" + configurationId + ")"; } @Override public boolean isSavingPossible() { return true; } @Override public boolean isSavingPersistent() { return true; } @Override public void save(String key, String value) throws IOException { final Map<String, String> configToSend = new HashMap<String, String>(configuration); configToSend.put(key, value); elasticsearchClient.sendAsJson("PUT", path, Collections.singletonMap("configuration", EsConfigurationDto.of(configToSend))); configuration.put(key, value); } @Override public void reload() throws IOException { final JsonNode source = elasticsearchClient.getJson(path).get("_source").get("configuration"); List<EsConfigurationDto> configAsList = JsonUtils.getMapper().readValue(source.traverse(), new TypeReference<List<EsConfigurationDto>>() {}); configuration = EsConfigurationDto.toMap(configAsList); } @JsonAutoDetect(fieldVisibility = ANY, getterVisibility = NONE, setterVisibility = NONE) private static class EsConfigurationDto { final String key; final String value; @JsonCreator private EsConfigurationDto(@JsonProperty("key") String key, @JsonProperty("value") String value) { this.key = key; this.value = value; } private static List<EsConfigurationDto> of(Map<String, String> configMap) { List<EsConfigurationDto> config = new ArrayList<EsConfigurationDto>(configMap.size()); for (Map.Entry<String, String> entry : configMap.entrySet()) { config.add(new EsConfigurationDto(entry.getKey(), entry.getValue())); } return config; } private static ConcurrentMap<String, String> toMap(List<EsConfigurationDto> configAsList) { ConcurrentMap<String, String> configAsMap = new ConcurrentHashMap<String, String>(); for (EsConfigurationDto dto : configAsList) { configAsMap.put(dto.key, dto.value); } return configAsMap; } } }