package org.elasticsearch.plugin.rest; import java.io.IOException; import java.io.OutputStream; import java.util.HashMap; import org.elasticsearch.rest.BytesRestResponse; import org.elasticsearch.rest.RestChannel; import org.elasticsearch.rest.RestController; import org.elasticsearch.rest.RestRequest; import org.elasticsearch.rest.RestResponse; import org.elasticsearch.rest.RestStatus; import org.elasticsearch.action.deletebyquery.DeleteByQueryResponse; import org.elasticsearch.action.search.SearchResponse; import org.elasticsearch.client.Client; import org.elasticsearch.common.inject.Inject; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.common.xcontent.XContent; import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.common.xcontent.XContentType; import static org.elasticsearch.rest.RestRequest.Method.GET; import static org.elasticsearch.rest.RestRequest.Method.POST; import org.elasticsearch.rest.BaseRestHandler; import org.elasticsearch.rest.action.support.RestBuilderListener; import org.elasticsearch.rest.support.RestUtils; import com.everdata.command.CommandException; import com.everdata.command.ReportResponse; import com.everdata.command.Search; import com.everdata.command.Search.QueryResponse; import com.everdata.parser.AST_Start; import com.everdata.parser.CommandParser; import com.everdata.parser.ParseException; import com.everdata.xcontent.CsvXContent; public class CommandRestHandler extends BaseRestHandler { @Inject public CommandRestHandler(Settings settings, Client client, RestController controller) { super(settings, controller, client); controller.registerHandler(GET, "/_command", this); controller.registerHandler(POST, "/_command", this); } @Override public void handleRequest(RestRequest request, final RestChannel channel, Client client) { String command = ""; if (request.method() == RestRequest.Method.GET) command = request.param("q", ""); else { HashMap<String, String> post = new HashMap<String, String>(); RestUtils.decodeQueryString(request.content().toUtf8(), 0, post); if (post.containsKey("q")) { command = post.get("q"); } } if (command.length() == 0) { SendFailure(request, channel, new CommandException("命令为空")); return; } else { if (!command.startsWith(Search.PREFIX_SEARCH_STRING)) command = Search.PREFIX_SEARCH_STRING + " " + command; } logger.info(command); final int from = request.paramAsInt("from", 0); final int size = request.paramAsInt("size", 10); final String format = request.param("format", "json"); final boolean download = request.paramAsBoolean("download", false); final boolean download2 = request.paramAsBoolean("download2", false); final boolean showMeta = request.paramAsBoolean("showMeta", true); XContent xContent = XContentType.JSON.xContent(); if (format.equalsIgnoreCase("csv")) xContent = CsvXContent.csvXContent; final Search search; try { CommandParser parser = new CommandParser(command); AST_Start.dumpWithLogger(logger, parser.getInnerTree(), ""); search = new Search(parser, client, logger); } catch (CommandException e2) { SendFailure(request, channel, e2); return; } catch (ParseException e1) { SendFailure(request, channel, e1); return; } catch (IOException e) { SendFailure(request, channel, e); return; } if (request.paramAsBoolean("delete", false)) { search.executeDelete(new RestBuilderListener<DeleteByQueryResponse>( channel) { @Override public RestResponse buildResponse(DeleteByQueryResponse result, XContentBuilder builder) throws Exception { search.buildDelete(builder, result); return new BytesRestResponse(result.status(), builder); } }); return; } if (request.paramAsBoolean("query", true)) { if (download || download2) { search.executeDownload(new OutputStream() { byte[] innerBuffer = new byte[1200]; int idx = 0; @Override public void write(int b) throws IOException { innerBuffer[idx++] = (byte) b; if (idx == innerBuffer.length) { /* channel.sendContinuousBytes(innerBuffer, 0, idx, false); */ idx = 0; } } @Override public void close() throws IOException { /* if (idx > 0) channel.sendContinuousBytes(innerBuffer, 0, idx, true); else channel.sendContinuousBytes(null, 0, 0, true); */ } }, xContent, download2); } else if (search.joinSearchs.size() > 0) { search.executeQuery(new RestBuilderListener<QueryResponse>( channel) { @Override public RestResponse buildResponse(QueryResponse result, XContentBuilder builder) throws Exception { Search.buildQuery(from, builder, result, logger, search.tableFieldNames, showMeta); return new BytesRestResponse(RestStatus.OK, builder); } }, from, size, new String[0]); } else { search.executeQueryWithNonJoin( new RestBuilderListener<SearchResponse>(channel) { @Override public RestResponse buildResponse( SearchResponse result, XContentBuilder builder) throws Exception { Search.buildQuery(from, builder, result, logger, search.tableFieldNames, showMeta); return new BytesRestResponse(RestStatus.OK, builder); } }, from, size, new String[0]); } } else { final ReportResponse result = new ReportResponse(); result.bucketFields = search.bucketFields; result.statsFields = search.statsFields; search.executeReport(new RestBuilderListener<SearchResponse>( channel) { @Override public RestResponse buildResponse(SearchResponse response, XContentBuilder builder) throws Exception { result.response = response; Search.buildReport(from, size, builder, result, logger); return new BytesRestResponse(response.status(), builder); } }, from, size); } } public void SendFailure(RestRequest request, RestChannel channel, Throwable e) { try { channel.sendResponse(new BytesRestResponse(channel, e)); } catch (IOException e1) { logger.error("Failed to send failure response", e1); } } }