Skip to content

Commit a564c95

Browse files
committed
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
1 parent 78640a0 commit a564c95

File tree

18 files changed

+76
-80
lines changed

18 files changed

+76
-80
lines changed

modules/percolator/src/main/java/org/elasticsearch/percolator/PercolateQueryBuilder.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ public class PercolateQueryBuilder extends AbstractQueryBuilder<PercolateQueryBu
133133
*/
134134
@Deprecated
135135
public PercolateQueryBuilder(String field, String documentType, BytesReference document) {
136-
this(field, documentType, Collections.singletonList(document), XContentFactory.xContentType(document));
136+
this(field, documentType, Collections.singletonList(document), XContentHelper.xContentType(document));
137137
}
138138

139139
/**
@@ -276,7 +276,7 @@ public PercolateQueryBuilder(String field, String documentType, String indexedDo
276276
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
277277
documentXContentType = in.readEnum(XContentType.class);
278278
} else {
279-
documentXContentType = XContentFactory.xContentType(documents.iterator().next());
279+
documentXContentType = XContentHelper.xContentType(documents.iterator().next());
280280
}
281281
} else {
282282
documentXContentType = null;
@@ -525,7 +525,7 @@ protected QueryBuilder doRewrite(QueryRewriteContext queryShardContext) {
525525
return this; // not executed yet
526526
} else {
527527
return new PercolateQueryBuilder(field, documentType, Collections.singletonList(source),
528-
XContentFactory.xContentType(source));
528+
XContentHelper.xContentType(source));
529529
}
530530
}
531531
GetRequest getRequest = new GetRequest(indexedDocumentIndex, indexedDocumentType, indexedDocumentId);

server/src/main/java/org/elasticsearch/action/admin/cluster/storedscripts/PutStoredScriptRequest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ public void readFrom(StreamInput in) throws IOException {
125125
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
126126
xContentType = in.readEnum(XContentType.class);
127127
} else {
128-
xContentType = XContentFactory.xContentType(content);
128+
xContentType = XContentHelper.xContentType(content);
129129
}
130130
if (in.getVersion().onOrAfter(Version.V_6_0_0_alpha2)) {
131131
context = in.readOptionalString();

server/src/main/java/org/elasticsearch/action/ingest/PutPipelineRequest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import org.elasticsearch.common.bytes.BytesReference;
2626
import org.elasticsearch.common.io.stream.StreamInput;
2727
import org.elasticsearch.common.io.stream.StreamOutput;
28-
import org.elasticsearch.common.xcontent.XContentFactory;
28+
import org.elasticsearch.common.xcontent.XContentHelper;
2929
import org.elasticsearch.common.xcontent.XContentType;
3030

3131
import java.io.IOException;
@@ -43,7 +43,7 @@ public class PutPipelineRequest extends AcknowledgedRequest<PutPipelineRequest>
4343
*/
4444
@Deprecated
4545
public PutPipelineRequest(String id, BytesReference source) {
46-
this(id, source, XContentFactory.xContentType(source));
46+
this(id, source, XContentHelper.xContentType(source));
4747
}
4848

4949
/**
@@ -83,7 +83,7 @@ public void readFrom(StreamInput in) throws IOException {
8383
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
8484
xContentType = in.readEnum(XContentType.class);
8585
} else {
86-
xContentType = XContentFactory.xContentType(source);
86+
xContentType = XContentHelper.xContentType(source);
8787
}
8888
}
8989

server/src/main/java/org/elasticsearch/action/ingest/SimulatePipelineRequest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
import org.elasticsearch.common.bytes.BytesReference;
2626
import org.elasticsearch.common.io.stream.StreamInput;
2727
import org.elasticsearch.common.io.stream.StreamOutput;
28-
import org.elasticsearch.common.xcontent.XContentFactory;
28+
import org.elasticsearch.common.xcontent.XContentHelper;
2929
import org.elasticsearch.common.xcontent.XContentType;
3030
import org.elasticsearch.index.VersionType;
3131
import org.elasticsearch.ingest.ConfigurationUtils;
@@ -55,7 +55,7 @@ public class SimulatePipelineRequest extends ActionRequest {
5555
*/
5656
@Deprecated
5757
public SimulatePipelineRequest(BytesReference source) {
58-
this(source, XContentFactory.xContentType(source));
58+
this(source, XContentHelper.xContentType(source));
5959
}
6060

6161
/**
@@ -107,7 +107,7 @@ public void readFrom(StreamInput in) throws IOException {
107107
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
108108
xContentType = in.readEnum(XContentType.class);
109109
} else {
110-
xContentType = XContentFactory.xContentType(source);
110+
xContentType = XContentHelper.xContentType(source);
111111
}
112112
}
113113

server/src/main/java/org/elasticsearch/action/termvectors/TermVectorsRequest.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535
import org.elasticsearch.common.lucene.uid.Versions;
3636
import org.elasticsearch.common.util.set.Sets;
3737
import org.elasticsearch.common.xcontent.XContentBuilder;
38-
import org.elasticsearch.common.xcontent.XContentFactory;
38+
import org.elasticsearch.common.xcontent.XContentHelper;
3939
import org.elasticsearch.common.xcontent.XContentParser;
4040
import org.elasticsearch.common.xcontent.XContentType;
4141
import org.elasticsearch.index.VersionType;
@@ -265,7 +265,7 @@ public TermVectorsRequest doc(XContentBuilder documentBuilder) {
265265
*/
266266
@Deprecated
267267
public TermVectorsRequest doc(BytesReference doc, boolean generateRandomId) {
268-
return this.doc(doc, generateRandomId, XContentFactory.xContentType(doc));
268+
return this.doc(doc, generateRandomId, XContentHelper.xContentType(doc));
269269
}
270270

271271
/**
@@ -519,7 +519,7 @@ public void readFrom(StreamInput in) throws IOException {
519519
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
520520
xContentType = in.readEnum(XContentType.class);
521521
} else {
522-
xContentType = XContentFactory.xContentType(doc);
522+
xContentType = XContentHelper.xContentType(doc);
523523
}
524524
}
525525
routing = in.readOptionalString();

server/src/main/java/org/elasticsearch/common/compress/CompressorFactory.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@
2424
import org.elasticsearch.common.io.Streams;
2525
import org.elasticsearch.common.io.stream.BytesStreamOutput;
2626
import org.elasticsearch.common.io.stream.StreamInput;
27-
import org.elasticsearch.common.xcontent.XContentFactory;
27+
import org.elasticsearch.common.xcontent.XContentHelper;
2828
import org.elasticsearch.common.xcontent.XContentType;
2929

3030
import java.io.IOException;
@@ -44,11 +44,11 @@ public static Compressor compressor(BytesReference bytes) {
4444
// bytes should be either detected as compressed or as xcontent,
4545
// if we have bytes that can be either detected as compressed or
4646
// as a xcontent, we have a problem
47-
assert XContentFactory.xContentType(bytes) == null;
47+
assert XContentHelper.xContentType(bytes) == null;
4848
return COMPRESSOR;
4949
}
5050

51-
XContentType contentType = XContentFactory.xContentType(bytes);
51+
XContentType contentType = XContentHelper.xContentType(bytes);
5252
if (contentType == null) {
5353
if (isAncient(bytes)) {
5454
throw new IllegalStateException("unsupported compression: index was created before v2.0.0.beta1 and wasn't upgraded?");

server/src/main/java/org/elasticsearch/common/xcontent/XContentFactory.java

Lines changed: 22 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,6 @@
2222
import com.fasterxml.jackson.dataformat.cbor.CBORConstants;
2323
import com.fasterxml.jackson.dataformat.smile.SmileConstants;
2424
import org.elasticsearch.ElasticsearchParseException;
25-
import org.elasticsearch.common.bytes.BytesArray;
26-
import org.elasticsearch.common.bytes.BytesReference;
27-
import org.elasticsearch.common.io.Streams;
2825
import org.elasticsearch.common.xcontent.cbor.CborXContent;
2926
import org.elasticsearch.common.xcontent.json.JsonXContent;
3027
import org.elasticsearch.common.xcontent.smile.SmileXContent;
@@ -221,18 +218,6 @@ public static XContent xContent(byte[] data, int offset, int length) {
221218
return xContent(type);
222219
}
223220

224-
/**
225-
* Guesses the content type based on the provided bytes.
226-
*
227-
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
228-
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
229-
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
230-
*/
231-
@Deprecated
232-
public static XContentType xContentType(byte[] data) {
233-
return xContentType(data, 0, data.length);
234-
}
235-
236221
/**
237222
* Guesses the content type based on the provided input stream without consuming it.
238223
*
@@ -248,8 +233,15 @@ public static XContentType xContentType(InputStream si) throws IOException {
248233
si.mark(GUESS_HEADER_LENGTH);
249234
try {
250235
final byte[] firstBytes = new byte[GUESS_HEADER_LENGTH];
251-
final int read = Streams.readFully(si, firstBytes);
252-
return xContentType(new BytesArray(firstBytes, 0, read));
236+
int read = 0;
237+
while (read < GUESS_HEADER_LENGTH) {
238+
final int r = si.read(firstBytes, read, GUESS_HEADER_LENGTH - read);
239+
if (r == -1) {
240+
break;
241+
}
242+
read += r;
243+
}
244+
return xContentType(firstBytes, 0, read);
253245
} finally {
254246
si.reset();
255247
}
@@ -263,24 +255,8 @@ public static XContentType xContentType(InputStream si) throws IOException {
263255
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
264256
*/
265257
@Deprecated
266-
public static XContentType xContentType(byte[] data, int offset, int length) {
267-
return xContentType(new BytesArray(data, offset, length));
268-
}
269-
270-
/**
271-
* Guesses the content type based on the provided bytes and returns the corresponding {@link XContent}
272-
*
273-
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
274-
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
275-
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
276-
*/
277-
@Deprecated
278-
public static XContent xContent(BytesReference bytes) {
279-
XContentType type = xContentType(bytes);
280-
if (type == null) {
281-
throw new ElasticsearchParseException("Failed to derive xcontent");
282-
}
283-
return xContent(type);
258+
public static XContentType xContentType(byte[] bytes) {
259+
return xContentType(bytes, 0, bytes.length);
284260
}
285261

286262
/**
@@ -291,19 +267,21 @@ public static XContent xContent(BytesReference bytes) {
291267
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
292268
*/
293269
@Deprecated
294-
public static XContentType xContentType(BytesReference bytes) {
295-
int length = bytes.length();
296-
if (length == 0) {
270+
public static XContentType xContentType(byte[] bytes, int offset, int length) {
271+
int totalLength = bytes.length;
272+
if (totalLength == 0 || length == 0) {
273+
return null;
274+
} else if ((offset + length) > totalLength) {
297275
return null;
298276
}
299-
byte first = bytes.get(0);
277+
byte first = bytes[offset];
300278
if (first == '{') {
301279
return XContentType.JSON;
302280
}
303-
if (length > 2 && first == SmileConstants.HEADER_BYTE_1 && bytes.get(1) == SmileConstants.HEADER_BYTE_2 && bytes.get(2) == SmileConstants.HEADER_BYTE_3) {
281+
if (length > 2 && first == SmileConstants.HEADER_BYTE_1 && bytes[offset + 1] == SmileConstants.HEADER_BYTE_2 && bytes[offset + 2] == SmileConstants.HEADER_BYTE_3) {
304282
return XContentType.SMILE;
305283
}
306-
if (length > 2 && first == '-' && bytes.get(1) == '-' && bytes.get(2) == '-') {
284+
if (length > 2 && first == '-' && bytes[offset + 1] == '-' && bytes[offset + 2] == '-') {
307285
return XContentType.YAML;
308286
}
309287
// CBOR logic similar to CBORFactory#hasCBORFormat
@@ -312,7 +290,7 @@ public static XContentType xContentType(BytesReference bytes) {
312290
}
313291
if (CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_TAG, first) && length > 2) {
314292
// Actually, specific "self-describe tag" is a very good indicator
315-
if (first == (byte) 0xD9 && bytes.get(1) == (byte) 0xD9 && bytes.get(2) == (byte) 0xF7) {
293+
if (first == (byte) 0xD9 && bytes[offset + 1] == (byte) 0xD9 && bytes[offset + 2] == (byte) 0xF7) {
316294
return XContentType.CBOR;
317295
}
318296
}
@@ -324,13 +302,13 @@ public static XContentType xContentType(BytesReference bytes) {
324302

325303
int jsonStart = 0;
326304
// JSON may be preceded by UTF-8 BOM
327-
if (length > 3 && first == (byte) 0xEF && bytes.get(1) == (byte) 0xBB && bytes.get(2) == (byte) 0xBF) {
305+
if (length > 3 && first == (byte) 0xEF && bytes[offset + 1] == (byte) 0xBB && bytes[offset + 2] == (byte) 0xBF) {
328306
jsonStart = 3;
329307
}
330308

331309
// a last chance for JSON
332310
for (int i = jsonStart; i < length; i++) {
333-
byte b = bytes.get(i);
311+
byte b = bytes[offset + i];
334312
if (b == '{') {
335313
return XContentType.JSON;
336314
}

server/src/main/java/org/elasticsearch/common/xcontent/XContentHelper.java

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
package org.elasticsearch.common.xcontent;
2121

22+
import org.apache.lucene.util.BytesRef;
2223
import org.elasticsearch.ElasticsearchParseException;
2324
import org.elasticsearch.common.Strings;
2425
import org.elasticsearch.common.bytes.BytesReference;
@@ -55,7 +56,7 @@ public static XContentParser createParser(NamedXContentRegistry xContentRegistry
5556
final XContentType contentType = XContentFactory.xContentType(compressedInput);
5657
return XContentFactory.xContent(contentType).createParser(xContentRegistry, deprecationHandler, compressedInput);
5758
} else {
58-
return XContentFactory.xContent(bytes).createParser(xContentRegistry, deprecationHandler, bytes.streamInput());
59+
return XContentFactory.xContent(xContentType(bytes)).createParser(xContentRegistry, deprecationHandler, bytes.streamInput());
5960
}
6061
}
6162

@@ -151,7 +152,7 @@ public static String convertToJson(BytesReference bytes, boolean reformatJson) t
151152

152153
@Deprecated
153154
public static String convertToJson(BytesReference bytes, boolean reformatJson, boolean prettyPrint) throws IOException {
154-
return convertToJson(bytes, reformatJson, prettyPrint, XContentFactory.xContentType(bytes));
155+
return convertToJson(bytes, reformatJson, prettyPrint, XContentFactory.xContentType(bytes.toBytesRef().bytes));
155156
}
156157

157158
public static String convertToJson(BytesReference bytes, boolean reformatJson, XContentType xContentType) throws IOException {
@@ -436,4 +437,17 @@ public static BytesReference toXContent(ToXContent toXContent, XContentType xCon
436437
return BytesReference.bytes(builder);
437438
}
438439
}
440+
441+
/**
442+
* Guesses the content type based on the provided bytes.
443+
*
444+
* @deprecated the content type should not be guessed except for few cases where we effectively don't know the content type.
445+
* The REST layer should move to reading the Content-Type header instead. There are other places where auto-detection may be needed.
446+
* This method is deprecated to prevent usages of it from spreading further without specific reasons.
447+
*/
448+
@Deprecated
449+
public static XContentType xContentType(BytesReference bytes) {
450+
BytesRef br = bytes.toBytesRef();
451+
return XContentFactory.xContentType(br.bytes, br.offset, br.length);
452+
}
439453
}

server/src/main/java/org/elasticsearch/index/query/MoreLikeThisQueryBuilder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.elasticsearch.common.xcontent.ToXContentObject;
4949
import org.elasticsearch.common.xcontent.XContentBuilder;
5050
import org.elasticsearch.common.xcontent.XContentFactory;
51+
import org.elasticsearch.common.xcontent.XContentHelper;
5152
import org.elasticsearch.common.xcontent.XContentParser;
5253
import org.elasticsearch.common.xcontent.XContentType;
5354
import org.elasticsearch.index.VersionType;
@@ -225,7 +226,7 @@ public Item(@Nullable String index, @Nullable String type, XContentBuilder doc)
225226
if (in.getVersion().onOrAfter(Version.V_5_3_0)) {
226227
xContentType = in.readEnum(XContentType.class);
227228
} else {
228-
xContentType = XContentFactory.xContentType(doc);
229+
xContentType = XContentHelper.xContentType(doc);
229230
}
230231
} else {
231232
id = in.readString();

server/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionBuilder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
3939
import org.elasticsearch.common.xcontent.XContentBuilder;
4040
import org.elasticsearch.common.xcontent.XContentFactory;
41+
import org.elasticsearch.common.xcontent.XContentHelper;
4142
import org.elasticsearch.common.xcontent.XContentParser;
4243
import org.elasticsearch.index.fielddata.IndexGeoPointFieldData;
4344
import org.elasticsearch.index.fielddata.IndexNumericFieldData;
@@ -186,7 +187,7 @@ protected ScoreFunction doToFunction(QueryShardContext context) throws IOExcepti
186187
AbstractDistanceScoreFunction scoreFunction;
187188
// EMPTY is safe because parseVariable doesn't use namedObject
188189
try (InputStream stream = functionBytes.streamInput();
189-
XContentParser parser = XContentFactory.xContent(functionBytes)
190+
XContentParser parser = XContentFactory.xContent(XContentHelper.xContentType(functionBytes))
190191
.createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, stream)) {
191192
scoreFunction = parseVariable(fieldName, parser, context, multiValueMode);
192193
}

server/src/main/java/org/elasticsearch/index/reindex/ClientScrollableHitSource.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
import org.elasticsearch.common.unit.TimeValue;
3939
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
4040
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
41-
import org.elasticsearch.common.xcontent.XContentFactory;
41+
import org.elasticsearch.common.xcontent.XContentHelper;
4242
import org.elasticsearch.common.xcontent.XContentType;
4343
import org.elasticsearch.index.mapper.ParentFieldMapper;
4444
import org.elasticsearch.index.mapper.RoutingFieldMapper;
@@ -236,7 +236,7 @@ public BytesReference getSource() {
236236

237237
@Override
238238
public XContentType getXContentType() {
239-
return XContentFactory.xContentType(source);
239+
return XContentHelper.xContentType(source);
240240
}
241241
@Override
242242
public long getVersion() {

server/src/main/java/org/elasticsearch/index/shard/IndexShard.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
import org.apache.lucene.search.UsageTrackingQueryCachingPolicy;
3838
import org.apache.lucene.store.AlreadyClosedException;
3939
import org.apache.lucene.util.BytesRef;
40-
import org.elasticsearch.core.internal.io.IOUtils;
4140
import org.apache.lucene.util.ThreadInterruptedException;
4241
import org.elasticsearch.Assertions;
4342
import org.elasticsearch.ElasticsearchException;
@@ -67,7 +66,8 @@
6766
import org.elasticsearch.common.util.BigArrays;
6867
import org.elasticsearch.common.util.concurrent.AbstractRunnable;
6968
import org.elasticsearch.common.util.concurrent.AsyncIOProcessor;
70-
import org.elasticsearch.common.xcontent.XContentFactory;
69+
import org.elasticsearch.common.xcontent.XContentHelper;
70+
import org.elasticsearch.core.internal.io.IOUtils;
7171
import org.elasticsearch.index.Index;
7272
import org.elasticsearch.index.IndexModule;
7373
import org.elasticsearch.index.IndexNotFoundException;
@@ -1250,7 +1250,8 @@ public Engine.Result applyTranslogOperation(Translog.Operation operation, Engine
12501250
// autoGeneratedID docs that are coming from the primary are updated correctly.
12511251
result = applyIndexOperation(index.seqNo(), index.primaryTerm(), index.version(),
12521252
index.versionType().versionTypeForReplicationAndRecovery(), index.getAutoGeneratedIdTimestamp(), true, origin,
1253-
source(shardId.getIndexName(), index.type(), index.id(), index.source(), XContentFactory.xContentType(index.source()))
1253+
source(shardId.getIndexName(), index.type(), index.id(), index.source(),
1254+
XContentHelper.xContentType(index.source()))
12541255
.routing(index.routing()).parent(index.parent()), onMappingUpdate);
12551256
break;
12561257
case DELETE:

0 commit comments

Comments
 (0)