/* * ModeShape (http://www.modeshape.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.modeshape.jcr.index.elasticsearch.client; import java.io.IOException; import org.apache.http.HttpStatus; import org.apache.http.client.methods.CloseableHttpResponse; import org.apache.http.client.methods.HttpDelete; import org.apache.http.client.methods.HttpGet; import org.apache.http.client.methods.HttpHead; import org.apache.http.client.methods.HttpPost; import org.apache.http.entity.ContentType; import org.apache.http.entity.StringEntity; import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClients; import org.modeshape.schematic.document.Document; import org.modeshape.jcr.index.elasticsearch.query.MatchAllQuery; /** * HTTP-based interface for the Elasticsearch engine. * * @author kulikov */ public class EsClient { private final String host; private final int port; /** * Creates new instance. * * @param host the address of the ES engine. * @param port the port number of ES engine. */ public EsClient(String host, int port) { this.host = host; this.port = port; } /** * Tests for the index existence with specified name. * * @param name the name of the index to test. * @return true if index with given name exists and false otherwise. * @throws IOException communication exception. */ public boolean indexExists(String name) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpHead head = new HttpHead(String.format("http://%s:%d/%s", host, port, name)); try { CloseableHttpResponse response = client.execute(head); return response.getStatusLine().getStatusCode() == HttpStatus.SC_OK; } finally { head.releaseConnection(); } } /** * Creates new index. * * @param name the name of the index to test. * @param type index type * @param mappings field mapping definition. * @return true if index was created. * @throws IOException communication exception. */ public boolean createIndex(String name, String type, EsRequest mappings) throws IOException { if (indexExists(name)) { return true; } CloseableHttpClient client = HttpClients.createDefault(); HttpPost method = new HttpPost(String.format("http://%s:%d/%s", host, port, name)); try { StringEntity requestEntity = new StringEntity(mappings.toString(), ContentType.APPLICATION_JSON); method.setEntity(requestEntity); CloseableHttpResponse resp = client.execute(method); return resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK; } finally { method.releaseConnection(); } } /** * Deletes index. * * @param name the name of the index to be deleted. * @return true if index was deleted. * @throws IOException */ public boolean deleteIndex(String name) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpDelete delete = new HttpDelete(String.format("http://%s:%d/%s", host, port, name)); try { CloseableHttpResponse resp = client.execute(delete); return resp.getStatusLine().getStatusCode() == HttpStatus.SC_OK; } finally { delete.releaseConnection(); } } /** * Indexes document. * * @param name the name of the index. * @param type index type * @param id document id * @param doc document * @return true if document was indexed. * @throws IOException */ public boolean storeDocument(String name, String type, String id, EsRequest doc) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpPost method = new HttpPost(String.format("http://%s:%d/%s/%s/%s", host, port, name, type, id)); try { StringEntity requestEntity = new StringEntity(doc.toString(), ContentType.APPLICATION_JSON); method.setEntity(requestEntity); CloseableHttpResponse resp = client.execute(method); int statusCode = resp.getStatusLine().getStatusCode(); return statusCode == HttpStatus.SC_CREATED || statusCode == HttpStatus.SC_OK; } finally { method.releaseConnection(); } } /** * Searches indexed document. * * @param name index name. * @param type index type. * @param id document identifier. * @return document if it was found or null. * @throws IOException */ public EsRequest getDocument(String name, String type, String id) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpGet method = new HttpGet(String.format("http://%s:%d/%s/%s/%s", host, port, name, type, id)); try { CloseableHttpResponse resp = client.execute(method); int status = resp.getStatusLine().getStatusCode(); switch (status) { case HttpStatus.SC_OK : EsResponse doc = EsResponse.read(resp.getEntity().getContent()); return new EsRequest((Document) doc.get("_source")); case HttpStatus.SC_NOT_ACCEPTABLE: case HttpStatus.SC_NOT_FOUND: return null; default: throw new IOException(resp.getStatusLine().getReasonPhrase()); } } finally { method.releaseConnection(); } } /** * Deletes document. * * @param name index name. * @param type index type. * @param id document id * @return true if it was deleted. * @throws IOException */ public boolean deleteDocument(String name, String type, String id) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpDelete delete = new HttpDelete(String.format("http://%s:%d/%s/%s/%s", host, port, name, type, id)); try { return client.execute(delete).getStatusLine().getStatusCode() == HttpStatus.SC_OK; } finally { delete.releaseConnection(); } } /** * Deletes all documents. * * @param name index name * @param type index type. * @throws IOException */ public void deleteAll(String name, String type) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpPost method = new HttpPost(String.format("http://%s:%d/%s/%s", host, port, name, type)); try { EsRequest query = new EsRequest(); query.put("query", new MatchAllQuery().build()); StringEntity requestEntity = new StringEntity(query.toString(), ContentType.APPLICATION_JSON); method.setEntity(requestEntity); method.setHeader(" X-HTTP-Method-Override", "DELETE"); CloseableHttpResponse resp = client.execute(method); int status = resp.getStatusLine().getStatusCode(); if (status != HttpStatus.SC_OK) { throw new IOException(resp.getStatusLine().getReasonPhrase()); } } finally { method.releaseConnection(); } } /** * Flushes index data. * * @param name index name. * @throws IOException */ public void flush(String name) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpPost method = new HttpPost(String.format("http://%s:%d/%s/_flush", host, port, name)); try { CloseableHttpResponse resp = client.execute(method); int status = resp.getStatusLine().getStatusCode(); if (status != HttpStatus.SC_OK) { throw new IOException(resp.getStatusLine().getReasonPhrase()); } } finally { method.releaseConnection(); } } /** * Refreshes index data. * * @param name index name. * @throws IOException */ public void refresh(String name) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpPost method = new HttpPost(String.format("http://%s:%d/%s/_refresh", host, port, name)); try { CloseableHttpResponse resp = client.execute(method); int status = resp.getStatusLine().getStatusCode(); if (status != HttpStatus.SC_OK) { throw new IOException(resp.getStatusLine().getReasonPhrase()); } } finally { method.releaseConnection(); } } /** * Executes query. * * @param name index name. * @param type index type. * @param query query to be executed * @return search results in json format. * @throws IOException */ public EsResponse search(String name, String type, EsRequest query) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpPost method = new HttpPost(String.format("http://%s:%d/%s/%s/_search", host, port, name, type)); try { StringEntity requestEntity = new StringEntity(query.toString(), ContentType.APPLICATION_JSON); method.setEntity(requestEntity); CloseableHttpResponse resp = client.execute(method); int status = resp.getStatusLine().getStatusCode(); if (status != HttpStatus.SC_OK) { throw new IOException(resp.getStatusLine().getReasonPhrase()); } return EsResponse.read(resp.getEntity().getContent()); } finally { method.releaseConnection(); } } /** * Counts entries. * * @param name index name. * @param type index type. * @return number of indexed entries. * @throws IOException */ public long count(String name, String type) throws IOException { CloseableHttpClient client = HttpClients.createDefault(); HttpPost method = new HttpPost(String.format("http://%s:%d/%s/%s/_count", host, port, name, type)); try { EsRequest query = new EsRequest(); query.put("query", new MatchAllQuery().build()); StringEntity requestEntity = new StringEntity(query.toString(), ContentType.APPLICATION_JSON); method.setEntity(requestEntity); CloseableHttpResponse resp = client.execute(method); int status = resp.getStatusLine().getStatusCode(); if (status != HttpStatus.SC_OK) { throw new IOException(resp.getStatusLine().getReasonPhrase()); } return (Integer) EsResponse.read(resp.getEntity().getContent()).get("count"); } finally { method.releaseConnection(); } } }