001package org.xbib.elasticsearch.rest;
002
003import org.elasticsearch.ElasticsearchException;
004import org.elasticsearch.common.xcontent.XContentBuilder;
005import org.elasticsearch.rest.RestRequest;
006import org.elasticsearch.rest.RestStatus;
007
008import java.io.IOException;
009
010import static org.elasticsearch.ExceptionsHelper.detailedMessage;
011import static org.xbib.elasticsearch.rest.RestXContentBuilder.restContentBuilder;
012
013public class XContentThrowableRestResponse extends XContentRestResponse {
014
015    public XContentThrowableRestResponse(RestRequest request, Throwable t) throws IOException {
016        this(request, ((t instanceof ElasticsearchException) ? ((ElasticsearchException) t).status() : RestStatus.INTERNAL_SERVER_ERROR), t);
017    }
018
019    public XContentThrowableRestResponse(RestRequest request, RestStatus status, Throwable t) throws IOException {
020        super(request, status, convert(request, status, t));
021    }
022
023    private static XContentBuilder convert(RestRequest request, RestStatus status, Throwable t) throws IOException {
024        XContentBuilder builder = restContentBuilder(request).startObject()
025                .field("error", detailedMessage(t))
026                .field("status", status.getStatus());
027        if (t != null && request.paramAsBoolean("error_trace", false)) {
028            builder.startObject("error_trace");
029            boolean first = true;
030            while (t != null) {
031                if (!first) {
032                    builder.startObject("cause");
033                }
034                buildThrowable(t, builder);
035                if (!first) {
036                    builder.endObject();
037                }
038                t = t.getCause();
039                first = false;
040            }
041            builder.endObject();
042        }
043        builder.endObject();
044        return builder;
045    }
046
047    private static void buildThrowable(Throwable t, XContentBuilder builder) throws IOException {
048        builder.field("message", t.getMessage());
049        for (StackTraceElement stElement : t.getStackTrace()) {
050            builder.startObject("at")
051                    .field("class", stElement.getClassName())
052                    .field("method", stElement.getMethodName());
053            if (stElement.getFileName() != null) {
054                builder.field("file", stElement.getFileName());
055            }
056            if (stElement.getLineNumber() >= 0) {
057                builder.field("line", stElement.getLineNumber());
058            }
059            builder.endObject();
060        }
061    }
062}