Remove BytesArray and BytesReference usage from XContentFactory (#29151)

* Remove BytesArray and BytesReference usage from XContentFactory

This removes the usage of `BytesArray` and `BytesReference` from
`XContentFactory`. Instead, a regular `byte[]` should be passed. To assist with
this a helper has been added to `XContentHelper` that will preserve the offset
and length from the underlying BytesReference.

This is part of ongoing work to separate the XContent parts from ES so they can
be factored into their own jar.

Relates to #28504
This commit is contained in:
Lee Hinman 2018-03-20 11:52:26 -06:00 committed by GitHub
parent 4bd217c94f
commit b4af451ec5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 76 additions and 82 deletions

View File

@ -133,7 +133,7 @@ public class PercolateQueryBuilder extends AbstractQueryBuilder<PercolateQueryBu
*/
@Deprecated
public PercolateQueryBuilder(String field, String documentType, BytesReference document) {
this(field, documentType, Collections.singletonList(document), XContentFactory.xContentType(document));
this(field, documentType, Collections.singletonList(document), XContentHelper.xContentType(document));
}
/**
@ -276,7 +276,7 @@ public class PercolateQueryBuilder extends AbstractQueryBuilder<PercolateQueryBu
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
documentXContentType = in.readEnum(XContentType.class);
} else {
documentXContentType = XContentFactory.xContentType(documents.iterator().next());
documentXContentType = XContentHelper.xContentType(documents.iterator().next());
}
} else {
documentXContentType = null;
@ -525,7 +525,7 @@ public class PercolateQueryBuilder extends AbstractQueryBuilder<PercolateQueryBu
return this; // not executed yet
} else {
return new PercolateQueryBuilder(field, documentType, Collections.singletonList(source),
XContentFactory.xContentType(source));
XContentHelper.xContentType(source));
}
}
GetRequest getRequest = new GetRequest(indexedDocumentIndex, indexedDocumentType, indexedDocumentId);

View File

@ -125,7 +125,7 @@ public class PutStoredScriptRequest extends AcknowledgedRequest<PutStoredScriptR
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
xContentType = in.readEnum(XContentType.class);
} else {
xContentType = XContentFactory.xContentType(content);
xContentType = XContentHelper.xContentType(content);
}
if (in.getVersion().onOrAfter(Version.V_6_0_0_alpha2)) {
context = in.readOptionalString();

View File

@ -25,7 +25,7 @@ import org.elasticsearch.action.support.master.AcknowledgedRequest;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.IOException;
@ -43,7 +43,7 @@ public class PutPipelineRequest extends AcknowledgedRequest<PutPipelineRequest>
*/
@Deprecated
public PutPipelineRequest(String id, BytesReference source) {
this(id, source, XContentFactory.xContentType(source));
this(id, source, XContentHelper.xContentType(source));
}
/**
@ -83,7 +83,7 @@ public class PutPipelineRequest extends AcknowledgedRequest<PutPipelineRequest>
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
xContentType = in.readEnum(XContentType.class);
} else {
xContentType = XContentFactory.xContentType(source);
xContentType = XContentHelper.xContentType(source);
}
}

View File

@ -25,8 +25,7 @@ import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.VersionType;
import org.elasticsearch.ingest.ConfigurationUtils;
@ -56,7 +55,7 @@ public class SimulatePipelineRequest extends ActionRequest {
*/
@Deprecated
public SimulatePipelineRequest(BytesReference source) {
this(source, XContentFactory.xContentType(source));
this(source, XContentHelper.xContentType(source));
}
/**
@ -78,7 +77,7 @@ public class SimulatePipelineRequest extends ActionRequest {
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
xContentType = in.readEnum(XContentType.class);
} else {
xContentType = XContentFactory.xContentType(source);
xContentType = XContentHelper.xContentType(source);
}
}

View File

@ -35,7 +35,7 @@ import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.common.util.set.Sets;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.VersionType;
@ -265,7 +265,7 @@ public class TermVectorsRequest extends SingleShardRequest<TermVectorsRequest> i
*/
@Deprecated
public TermVectorsRequest doc(BytesReference doc, boolean generateRandomId) {
return this.doc(doc, generateRandomId, XContentFactory.xContentType(doc));
return this.doc(doc, generateRandomId, XContentHelper.xContentType(doc));
}
/**
@ -518,7 +518,7 @@ public class TermVectorsRequest extends SingleShardRequest<TermVectorsRequest> i
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
xContentType = in.readEnum(XContentType.class);
} else {
xContentType = XContentFactory.xContentType(doc);
xContentType = XContentHelper.xContentType(doc);
}
}
routing = in.readOptionalString();

View File

@ -24,7 +24,7 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
import java.io.IOException;
@ -44,11 +44,11 @@ public class CompressorFactory {
// bytes should be either detected as compressed or as xcontent,
// if we have bytes that can be either detected as compressed or
// as a xcontent, we have a problem
assert XContentFactory.xContentType(bytes) == null;
assert XContentHelper.xContentType(bytes) == null;
return COMPRESSOR;
}
XContentType contentType = XContentFactory.xContentType(bytes);
XContentType contentType = XContentHelper.xContentType(bytes);
if (contentType == null) {
if (isAncient(bytes)) {
throw new IllegalStateException("unsupported compression: index was created before v2.0.0.beta1 and wasn't upgraded?");

View File

@ -22,9 +22,6 @@ package org.elasticsearch.common.xcontent;
import com.fasterxml.jackson.dataformat.cbor.CBORConstants;
import com.fasterxml.jackson.dataformat.smile.SmileConstants;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.xcontent.cbor.CborXContent;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import org.elasticsearch.common.xcontent.smile.SmileXContent;
@ -221,18 +218,6 @@ public class XContentFactory {
return xContent(type);
}
/**
* Guesses the content type based on the provided bytes.
*
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
*/
@Deprecated
public static XContentType xContentType(byte[] data) {
return xContentType(data, 0, data.length);
}
/**
* Guesses the content type based on the provided input stream without consuming it.
*
@ -248,8 +233,15 @@ public class XContentFactory {
si.mark(GUESS_HEADER_LENGTH);
try {
final byte[] firstBytes = new byte[GUESS_HEADER_LENGTH];
final int read = Streams.readFully(si, firstBytes);
return xContentType(new BytesArray(firstBytes, 0, read));
int read = 0;
while (read < GUESS_HEADER_LENGTH) {
final int r = si.read(firstBytes, read, GUESS_HEADER_LENGTH - read);
if (r == -1) {
break;
}
read += r;
}
return xContentType(firstBytes, 0, read);
} finally {
si.reset();
}
@ -263,24 +255,8 @@ public class XContentFactory {
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
*/
@Deprecated
public static XContentType xContentType(byte[] data, int offset, int length) {
return xContentType(new BytesArray(data, offset, length));
}
/**
* Guesses the content type based on the provided bytes and returns the corresponding {@link XContent}
*
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
*/
@Deprecated
public static XContent xContent(BytesReference bytes) {
XContentType type = xContentType(bytes);
if (type == null) {
throw new ElasticsearchParseException("Failed to derive xcontent");
}
return xContent(type);
public static XContentType xContentType(byte[] bytes) {
return xContentType(bytes, 0, bytes.length);
}
/**
@ -291,19 +267,21 @@ public class XContentFactory {
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
*/
@Deprecated
public static XContentType xContentType(BytesReference bytes) {
int length = bytes.length();
if (length == 0) {
public static XContentType xContentType(byte[] bytes, int offset, int length) {
int totalLength = bytes.length;
if (totalLength == 0 || length == 0) {
return null;
} else if ((offset + length) > totalLength) {
return null;
}
byte first = bytes.get(0);
byte first = bytes[offset];
if (first == '{') {
return XContentType.JSON;
}
if (length > 2 && first == SmileConstants.HEADER_BYTE_1 && bytes.get(1) == SmileConstants.HEADER_BYTE_2 && bytes.get(2) == SmileConstants.HEADER_BYTE_3) {
if (length > 2 && first == SmileConstants.HEADER_BYTE_1 && bytes[offset + 1] == SmileConstants.HEADER_BYTE_2 && bytes[offset + 2] == SmileConstants.HEADER_BYTE_3) {
return XContentType.SMILE;
}
if (length > 2 && first == '-' && bytes.get(1) == '-' && bytes.get(2) == '-') {
if (length > 2 && first == '-' && bytes[offset + 1] == '-' && bytes[offset + 2] == '-') {
return XContentType.YAML;
}
// CBOR logic similar to CBORFactory#hasCBORFormat
@ -312,7 +290,7 @@ public class XContentFactory {
}
if (CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_TAG, first) && length > 2) {
// Actually, specific "self-describe tag" is a very good indicator
if (first == (byte) 0xD9 && bytes.get(1) == (byte) 0xD9 && bytes.get(2) == (byte) 0xF7) {
if (first == (byte) 0xD9 && bytes[offset + 1] == (byte) 0xD9 && bytes[offset + 2] == (byte) 0xF7) {
return XContentType.CBOR;
}
}
@ -324,13 +302,13 @@ public class XContentFactory {
int jsonStart = 0;
// JSON may be preceded by UTF-8 BOM
if (length > 3 && first == (byte) 0xEF && bytes.get(1) == (byte) 0xBB && bytes.get(2) == (byte) 0xBF) {
if (length > 3 && first == (byte) 0xEF && bytes[offset + 1] == (byte) 0xBB && bytes[offset + 2] == (byte) 0xBF) {
jsonStart = 3;
}
// a last chance for JSON
for (int i = jsonStart; i < length; i++) {
byte b = bytes.get(i);
byte b = bytes[offset + i];
if (b == '{') {
return XContentType.JSON;
}

View File

@ -19,6 +19,7 @@
package org.elasticsearch.common.xcontent;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
@ -55,7 +56,7 @@ public class XContentHelper {
final XContentType contentType = XContentFactory.xContentType(compressedInput);
return XContentFactory.xContent(contentType).createParser(xContentRegistry, deprecationHandler, compressedInput);
} else {
return XContentFactory.xContent(bytes).createParser(xContentRegistry, deprecationHandler, bytes.streamInput());
return XContentFactory.xContent(xContentType(bytes)).createParser(xContentRegistry, deprecationHandler, bytes.streamInput());
}
}
@ -151,7 +152,7 @@ public class XContentHelper {
@Deprecated
public static String convertToJson(BytesReference bytes, boolean reformatJson, boolean prettyPrint) throws IOException {
return convertToJson(bytes, reformatJson, prettyPrint, XContentFactory.xContentType(bytes));
return convertToJson(bytes, reformatJson, prettyPrint, XContentFactory.xContentType(bytes.toBytesRef().bytes));
}
public static String convertToJson(BytesReference bytes, boolean reformatJson, XContentType xContentType) throws IOException {
@ -436,4 +437,17 @@ public class XContentHelper {
return BytesReference.bytes(builder);
}
}
/**
* Guesses the content type based on the provided bytes.
*
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
*/
@Deprecated
public static XContentType xContentType(BytesReference bytes) {
BytesRef br = bytes.toBytesRef();
return XContentFactory.xContentType(br.bytes, br.offset, br.length);
}
}

View File

@ -48,6 +48,7 @@ import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.VersionType;
@ -224,7 +225,7 @@ public class MoreLikeThisQueryBuilder extends AbstractQueryBuilder<MoreLikeThisQ
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
xContentType = in.readEnum(XContentType.class);
} else {
xContentType = XContentFactory.xContentType(doc);
xContentType = XContentHelper.xContentType(doc);
}
} else {
id = in.readString();

View File

@ -38,6 +38,7 @@ import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
@ -186,7 +187,7 @@ public abstract class DecayFunctionBuilder<DFB extends DecayFunctionBuilder<DFB>
AbstractDistanceScoreFunction scoreFunction;
// EMPTY is safe because parseVariable doesn't use namedObject
try (InputStream stream = functionBytes.streamInput();
XContentParser parser = XContentFactory.xContent(functionBytes)
XContentParser parser = XContentFactory.xContent(XContentHelper.xContentType(functionBytes))
.createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, stream)) {
scoreFunction = parseVariable(fieldName, parser, context, multiValueMode);
}

View File

@ -38,7 +38,7 @@ import org.elasticsearch.common.document.DocumentField;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.mapper.ParentFieldMapper;
import org.elasticsearch.index.mapper.RoutingFieldMapper;
@ -236,7 +236,7 @@ public class ClientScrollableHitSource extends ScrollableHitSource {
@Override
public XContentType getXContentType() {
return XContentFactory.xContentType(source);
return XContentHelper.xContentType(source);
}
@Override
public long getVersion() {

View File

@ -23,7 +23,6 @@ import com.carrotsearch.hppc.ObjectLongMap;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.apache.lucene.index.CheckIndex;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexCommit;
import org.apache.lucene.index.IndexOptions;
import org.apache.lucene.index.LeafReaderContext;
@ -37,7 +36,6 @@ import org.apache.lucene.search.Sort;
import org.apache.lucene.search.UsageTrackingQueryCachingPolicy;
import org.apache.lucene.store.AlreadyClosedException;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.core.internal.io.IOUtils;
import org.apache.lucene.util.ThreadInterruptedException;
import org.elasticsearch.Assertions;
import org.elasticsearch.ElasticsearchException;
@ -66,7 +64,8 @@ import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.util.BigArrays;
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
import org.elasticsearch.common.util.concurrent.AsyncIOProcessor;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.core.internal.io.IOUtils;
import org.elasticsearch.index.Index;
import org.elasticsearch.index.IndexModule;
import org.elasticsearch.index.IndexNotFoundException;
@ -1238,7 +1237,8 @@ public class IndexShard extends AbstractIndexShardComponent implements IndicesCl
// autoGeneratedID docs that are coming from the primary are updated correctly.
result = applyIndexOperation(index.seqNo(), index.primaryTerm(), index.version(),
index.versionType().versionTypeForReplicationAndRecovery(), index.getAutoGeneratedIdTimestamp(), true, origin,
source(shardId.getIndexName(), index.type(), index.id(), index.source(), XContentFactory.xContentType(index.source()))
source(shardId.getIndexName(), index.type(), index.id(), index.source(),
XContentHelper.xContentType(index.source()))
.routing(index.routing()).parent(index.parent()), onMappingUpdate);
break;
case DELETE:

View File

@ -30,7 +30,6 @@ import org.elasticsearch.common.xcontent.ContextParser;
import org.elasticsearch.common.xcontent.ObjectParser;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentType;
@ -123,7 +122,7 @@ public final class PipelineConfiguration extends AbstractDiffable<PipelineConfig
} else {
final String id = in.readString();
final BytesReference config = in.readBytesReference();
return new PipelineConfiguration(id, config, XContentFactory.xContentType(config));
return new PipelineConfiguration(id, config, XContentHelper.xContentType(config));
}
}

View File

@ -26,7 +26,7 @@ import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.BytesRestResponse;
import org.elasticsearch.rest.RestController;
@ -86,7 +86,7 @@ public class RestGetSourceAction extends BaseRestHandler {
} else {
final BytesReference source = response.getSourceInternal();
try (InputStream stream = source.streamInput()) {
builder.rawValue(stream, XContentFactory.xContentType(source));
builder.rawValue(stream, XContentHelper.xContentType(source));
}
return new BytesRestResponse(OK, builder);
}

View File

@ -24,7 +24,7 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import java.io.IOException;
import java.io.InputStream;
@ -60,7 +60,7 @@ public class RawTaskStatus implements Task.Status {
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
try (InputStream stream = status.streamInput()) {
return builder.rawValue(stream, XContentFactory.xContentType(status));
return builder.rawValue(stream, XContentHelper.xContentType(status));
}
}

View File

@ -54,7 +54,7 @@ public class XContentFactoryTests extends ESTestCase {
builder.field("field1", "value1");
builder.endObject();
assertThat(XContentFactory.xContentType(BytesReference.bytes(builder)), equalTo(type));
assertThat(XContentHelper.xContentType(BytesReference.bytes(builder)), equalTo(type));
assertThat(XContentFactory.xContentType(BytesReference.bytes(builder).streamInput()), equalTo(type));
// CBOR is binary, cannot use String

View File

@ -28,6 +28,7 @@ import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
@ -61,7 +62,7 @@ public class SourceFieldMapperTests extends ESSingleNodeTestCase {
.endObject()),
XContentType.JSON));
assertThat(XContentFactory.xContentType(doc.source()), equalTo(XContentType.JSON));
assertThat(XContentFactory.xContentType(doc.source().toBytesRef().bytes), equalTo(XContentType.JSON));
documentMapper = parser.parse("type", new CompressedXContent(mapping));
doc = documentMapper.parse(SourceToParse.source("test", "type", "1", BytesReference.bytes(XContentFactory.smileBuilder().startObject()
@ -69,7 +70,7 @@ public class SourceFieldMapperTests extends ESSingleNodeTestCase {
.endObject()),
XContentType.SMILE));
assertThat(XContentFactory.xContentType(doc.source()), equalTo(XContentType.SMILE));
assertThat(XContentHelper.xContentType(doc.source()), equalTo(XContentType.SMILE));
}
public void testIncludes() throws Exception {

View File

@ -21,7 +21,7 @@ package org.elasticsearch.index.engine;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.index.IndexSettings;
import org.elasticsearch.index.analysis.AnalyzerScope;
import org.elasticsearch.index.analysis.IndexAnalyzers;
@ -121,7 +121,8 @@ public class TranslogHandler implements EngineConfig.TranslogRecoveryRunner {
final String indexName = mapperService.index().getName();
final Engine.Index engineIndex = IndexShard.prepareIndex(docMapper(index.type()),
mapperService.getIndexSettings().getIndexVersionCreated(),
source(indexName, index.type(), index.id(), index.source(), XContentFactory.xContentType(index.source()))
source(indexName, index.type(), index.id(), index.source(),
XContentHelper.xContentType(index.source()))
.routing(index.routing()).parent(index.parent()), index.seqNo(), index.primaryTerm(),
index.version(), index.versionType().versionTypeForReplicationAndRecovery(), origin,
index.getAutoGeneratedIdTimestamp(), true);