org.kitodo.data.elasticsearch.KitodoRestClient.java Source code

Java tutorial

Introduction

Here is the source code for org.kitodo.data.elasticsearch.KitodoRestClient.java

Source

/*
 * (c) Kitodo. Key to digital objects e. V. <contact@kitodo.org>
 *
 * This file is part of the Kitodo project.
 *
 * It is licensed under GNU General Public License version 3 or later.
 *
 * For the full copyright and license information, please read the
 * GPL3-License.txt file that was distributed with this source code.
 */

package org.kitodo.data.elasticsearch;

import java.io.IOException;
import java.util.Collections;

import javax.ws.rs.HttpMethod;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.StatusLine;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.entity.ContentType;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.nio.entity.NStringEntity;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.elasticsearch.action.main.MainResponse;
import org.elasticsearch.client.Response;
import org.elasticsearch.client.ResponseException;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.rest.RestStatus;
import org.kitodo.config.ConfigMain;
import org.kitodo.data.elasticsearch.api.RestClientInterface;
import org.kitodo.data.elasticsearch.exceptions.CustomResponseException;

/**
 * Implementation of Elastic Search REST Client for Index Module.
 */
public abstract class KitodoRestClient implements RestClientInterface {

    private static final Logger logger = LogManager.getLogger(KitodoRestClient.class);

    protected String index;
    protected String type;
    protected RestClient client;
    protected RestHighLevelClient highLevelClient;

    /**
     * Create REST client.
     *
     */
    protected void initiateClient() {
        String host = ConfigMain.getParameter("elasticsearch.host", "localhost");
        int port = ConfigMain.getIntParameter("elasticsearch.port", 9200);
        String protocol = ConfigMain.getParameter("elasticsearch.protocol", "http");
        initiateClient(host, port, protocol);
    }

    /**
     * Create REST client with other without basic authentication.
     *
     * @param host
     *            default host is localhost
     * @param port
     *            default port ist 9200
     * @param protocol
     *            default protocol is http
     */
    private void initiateClient(String host, Integer port, String protocol) {
        if (ConfigMain.getBooleanParameter("elasticsearch.useAuthentication")) {
            initiateClientWithAuth(host, port, protocol);
        } else {
            client = RestClient.builder(new HttpHost(host, port, protocol)).build();
            highLevelClient = new RestHighLevelClient(client);
        }
    }

    /**
     * Create REST client with basic authentication.
     * 
     * @param host
     *            default host is localhost
     * @param port
     *            default port ist 9200
     * @param protocol
     *            default protocol is http
     */
    private void initiateClientWithAuth(String host, Integer port, String protocol) {
        String user = ConfigMain.getParameter("elasticsearch.user", "elastic");
        String password = ConfigMain.getParameter("elasticsearch.password", "changeme");

        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials(user, password));

        client = RestClient.builder(new HttpHost(host, port, protocol))
                .setHttpClientConfigCallback(
                        httpClientBuilder -> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider))
                .build();
        highLevelClient = new RestHighLevelClient(client);
    }

    /**
     * Get information about client server.
     *
     * @return information about the server
     */
    public String getServerInformation() throws IOException {
        Response response = client.performRequest(HttpMethod.GET, "/", Collections.singletonMap("pretty", "true"));
        return EntityUtils.toString(response.getEntity());
    }

    /**
     * Get information about client server.
     *
     * @return information about the server
     */
    public String getServerInfo() throws IOException {
        MainResponse response = highLevelClient.info();
        return response.toString();
    }

    /**
     * Get mapping.
     *
     * @return mapping
     */
    public String getMapping() throws IOException {
        Response response = client.performRequest(HttpMethod.GET, "/" + index + "/_mapping",
                Collections.singletonMap("pretty", "true"));
        return EntityUtils.toString(response.getEntity());
    }

    /**
     * Create new index without mapping.
     */
    public boolean createIndex() throws IOException, CustomResponseException {
        return createIndex(null);
    }

    /**
     * Create new index with mapping.
     *
     * @param query
     *            contains mapping
     * @return true or false - can be used for displaying information to user if
     *         success
     */
    public boolean createIndex(String query) throws IOException, CustomResponseException {
        if (query == null) {
            query = "{\"settings\" : {\"index\" : {\"number_of_shards\" : 1,\"number_of_replicas\" : 0}}}";
        }
        HttpEntity entity = new NStringEntity(query, ContentType.APPLICATION_JSON);
        Response indexResponse = client.performRequest(HttpMethod.PUT, "/" + index, Collections.emptyMap(), entity);
        int statusCode = processStatusCode(indexResponse.getStatusLine());
        return statusCode == 200 || statusCode == 201;
    }

    /**
     * Check if index already exists. Needed for frontend.
     *
     * @return false if doesn't exists, true if exists
     */
    public boolean indexExists() throws IOException, CustomResponseException {
        Response indexResponse = client.performRequest(HttpMethod.GET, "/" + index, Collections.emptyMap());
        int statusCode = processStatusCode(indexResponse.getStatusLine());
        return statusCode == 200 || statusCode == 201;
    }

    /**
     * Delete the whole index. Used for cleaning after tests!
     */
    public void deleteIndex() throws IOException {
        client.performRequest(HttpMethod.DELETE, "/" + index);
    }

    /**
     * Getter for index.
     *
     * @return index name
     */
    public String getIndex() {
        return index;
    }

    /**
     * Setter for index.
     *
     * @param index
     *            - equal to the name of database, default kitodo
     */
    public void setIndex(String index) {
        this.index = index;
    }

    /**
     * Getter for type.
     *
     * @return type name
     */
    public String getType() {
        return type;
    }

    /**
     * Setter for type.
     *
     * @param type
     *            - equal to the name of table in database, but not necessary
     */
    public void setType(String type) {
        this.type = type;
    }

    protected void handleResponseException(ResponseException e) throws CustomResponseException {
        if (e.getResponse().getStatusLine().getStatusCode() == 404) {
            logger.debug(e.getMessage(), e);
        } else {
            throw new CustomResponseException(e);
        }
    }

    protected int processStatusCode(StatusLine statusLine) throws CustomResponseException {
        int statusCode = statusLine.getStatusCode();
        processStatusCode(statusCode, statusLine);
        return statusCode;
    }

    protected int processStatusCode(RestStatus restStatus) throws CustomResponseException {
        int statusCode = restStatus.getStatus();
        processStatusCode(statusCode, restStatus);
        return statusCode;
    }

    private void processStatusCode(int statusCode, Object restStatus) throws CustomResponseException {
        if (statusCode >= 400 && statusCode <= 499) {
            throw new CustomResponseException("Client error: " + restStatus.toString());
        } else if (statusCode >= 500 && statusCode <= 599) {
            throw new CustomResponseException("Server error: " + restStatus.toString());
        }
    }
}