blob: b363579bbfba612e4b25d7d7895e680ab8d9edca [file] [log] [blame]
/*******************************************************************************
* Copyright (C) 2017 ANSYS medini Technologies AG
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* ANSYS medini Technologies AG - initial API and implementation
******************************************************************************/
package org.eclipse.opencert.elastic;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Collections;
import java.util.Date;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.nio.client.DefaultAsyncUserTokenHandler;
import org.apache.http.nio.entity.NStringEntity;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.QueryStringQueryBuilder;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
/**
* {@link DefaultAsyncUserTokenHandler} implementation of {@link ElasticClient}.
*
* @author mauersberger
*/
public class ElasticClientImpl implements ElasticClient, AutoCloseable {
// the "real" client
private RestClient restClient;
@SuppressWarnings("unused")
private int lastStatus;
/**
* Factory method to create a new {@link ElasticClient}.
*
* @param host
* server name or IP
* @param port
* port
* @param scheme
* "http" or "https"
* @return the new {@link ElasticClient} instance
*/
public static ElasticClient on(String host, int port, String scheme) {
ElasticClientImpl client = new ElasticClientImpl();
client.restClient = RestClient.builder(new HttpHost(host, port, scheme)).build();
return client;
}
/*
* Intentionally private.
*/
private ElasticClientImpl() {
// just to avoid instantiation, force using the factory API
}
@Override
public ElasticClient store(ElasticDocument document) throws IOException {
HttpEntity entity = new NStringEntity(document.source.toString(), ContentType.APPLICATION_JSON);
Response response = this.restClient.performRequest("PUT", document.getEndPoint(), Collections.emptyMap(), entity); //$NON-NLS-1$
lastStatus = response.getStatusLine().getStatusCode();
return this;
}
@Override
public ElasticClient storeAll(Iterator<ElasticDocument> documents) throws IOException {
while (documents.hasNext()) {
store (documents.next());
}
return this;
}
@Override
public Set<ElasticDocument> search(String indexName, String queryString, Map<String, Object> filters) throws Exception {
RestHighLevelClient highLevel = new RestHighLevelClient(this.restClient);
SearchRequest searchRequest = new SearchRequest(indexName);
// see example at https://dzone.com/articles/java-high-level-rest-client-elasticsearch
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
searchRequest.source(sourceBuilder);
// find the best query builder depending on the arguments
QueryBuilder queryBuilder = QueryBuilders.matchAllQuery();
if (queryString != null) {
queryString = queryString.replaceAll(".*", "*");
QueryStringQueryBuilder stringQuery = QueryBuilders.queryStringQuery(queryString);
stringQuery.allowLeadingWildcard(true);
queryBuilder = stringQuery;
}
sourceBuilder.query(queryBuilder);
SearchResponse response = highLevel.search(searchRequest);
System.out.println(response);
lastStatus = response.status().getStatus();
Set<ElasticDocument> result = new HashSet<>();
SearchHits hits = response.getHits();
// Note: total hits might be much bigger
for (SearchHit hit : hits.getHits()) {
// convert Hit to Json
JsonObject json = new JsonObject();
// put all source information back into JSON
Map<String, Object> fields = hit.getSource();
Set<String> keys = fields.keySet();
for (String key : keys) {
Object field = fields.get(key);
json.addProperty(key, (String) field.toString());
}
ElasticDocument doc = new ElasticDocument(json, hit.getIndex(), hit.getType(), hit.getId());
result.add(doc);
}
return result;
}
@Override
public ElasticClient ping() throws Exception {
Response response = this.restClient.performRequest("GET", "/"); //$NON-NLS-1$ //$NON-NLS-2$
lastStatus = response.getStatusLine().getStatusCode();
return this;
}
@Override
public ElasticClient delete(String indexName) throws Exception {
Response response = this.restClient.performRequest("DELETE", "/" + indexName, Collections.emptyMap()); //$NON-NLS-1$ //$NON-NLS-2$
lastStatus = response.getStatusLine().getStatusCode();
return this;
}
@Override
public String version() throws IOException {
Response response = this.restClient.performRequest("GET", "/"); //$NON-NLS-1$ //$NON-NLS-2$
lastStatus = response.getStatusLine().getStatusCode();
// we assume its a JSON response
try (InputStream content = response.getEntity().getContent()) {
InputStreamReader reader = new InputStreamReader(content, "UTF8"); //$NON-NLS-1$
JsonObject json = new Gson().fromJson(reader, JsonObject.class);
return json.get("version").getAsJsonObject().get("number").getAsString(); //$NON-NLS-1$//$NON-NLS-2$
} catch (Exception exception) {
throw new IOException("Unable to ping server"); //$NON-NLS-1$
}
}
@Override
public String indexStatus(String indexName) throws Exception {
Response response = this.restClient.performRequest("GET", "/" + indexName); //$NON-NLS-1$ //$NON-NLS-2$
lastStatus = response.getStatusLine().getStatusCode();
// we assume its a JSON response
try (InputStream content = response.getEntity().getContent()) {
InputStreamReader reader = new InputStreamReader(content, "UTF8"); //$NON-NLS-1$
JsonObject root = new Gson().fromJson(reader, JsonObject.class);
JsonObject index = root.get(indexName).getAsJsonObject();
JsonObject settings = index.get("settings").getAsJsonObject(); //$NON-NLS-1$
JsonObject indexSettings = settings.get("index").getAsJsonObject(); //$NON-NLS-1$
long date = indexSettings.get("creation_date").getAsLong(); //$NON-NLS-1$
return "Created " + new Date(date).toString(); //$NON-NLS-1$
} catch (Exception exception) {
throw new IOException("Unable to ping index", exception); //$NON-NLS-1$
}
}
@Override
public void close() throws IOException {
if (restClient != null) {
restClient.close();
restClient = null;
}
}
}