From ad09bbe9c800de7bf66e0688bc3a696006c4b842 Mon Sep 17 00:00:00 2001 From: Nick Knize Date: Wed, 8 Feb 2023 10:28:38 -0600 Subject: [PATCH] [Refactor] Requests to use MediaType instead of XContentType (#6218) Refactors various REST requests to use MediaType instead of XContentType to abstract media format from the REST interfaces. Signed-off-by: Nicholas Walter Knize --- .../opensearch/client/RequestConverters.java | 24 ++++- .../client/indices/CreateIndexRequest.java | 93 +++++++++++++++++++ .../indices/PutIndexTemplateRequest.java | 46 ++++++++- .../client/indices/PutMappingRequest.java | 53 +++++++++-- .../indices/PutMappingRequestTests.java | 4 +- .../opensearch/common/xcontent/MediaType.java | 6 ++ .../opensearch/common/xcontent/XContent.java | 2 +- .../common/xcontent/XContentBuilder.java | 22 +++++ .../common/xcontent/XContentFactory.java | 2 +- .../common/xcontent/XContentGenerator.java | 14 +++ .../common/xcontent/XContentType.java | 6 -- .../common/xcontent/cbor/CborXContent.java | 3 +- .../common/xcontent/json/JsonXContent.java | 3 +- .../xcontent/json/JsonXContentGenerator.java | 73 +++++++++++++++ .../common/xcontent/smile/SmileXContent.java | 3 +- .../common/xcontent/yaml/YamlXContent.java | 3 +- .../indices/create/CreateIndexRequest.java | 90 ++++++++++++++++++ .../action/ingest/PutPipelineRequest.java | 16 ++++ .../opensearch/common/settings/Settings.java | 3 +- .../common/xcontent/XContentHelper.java | 85 ++++++++++++++--- .../index/reindex/ReindexRequest.java | 2 +- .../opensearch/OpenSearchExceptionTests.java | 8 +- .../SearchPhaseExecutionExceptionTests.java | 2 +- .../common/xcontent/BaseXContentTestCase.java | 4 +- .../opensearch/test/OpenSearchTestCase.java | 24 +++++ 25 files changed, 543 insertions(+), 48 deletions(-) diff --git a/client/rest-high-level/src/main/java/org/opensearch/client/RequestConverters.java b/client/rest-high-level/src/main/java/org/opensearch/client/RequestConverters.java index b3144a75d1445..bdd1023d5edd7 100644 --- a/client/rest-high-level/src/main/java/org/opensearch/client/RequestConverters.java +++ b/client/rest-high-level/src/main/java/org/opensearch/client/RequestConverters.java @@ -79,6 +79,7 @@ import org.opensearch.common.unit.TimeValue; import org.opensearch.common.util.CollectionUtils; import org.opensearch.common.xcontent.DeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.ToXContent; import org.opensearch.common.xcontent.XContent; @@ -112,6 +113,11 @@ import java.util.Map; import java.util.StringJoiner; +/** + * Converts OpenSearch writeable requests to an HTTP Request + * + * @opensearch.api + */ final class RequestConverters { static final XContentType REQUEST_BODY_CONTENT_TYPE = XContentType.JSON; @@ -514,7 +520,7 @@ static Request multiSearch(MultiSearchRequest multiSearchRequest) throws IOExcep XContent xContent = REQUEST_BODY_CONTENT_TYPE.xContent(); byte[] source = MultiSearchRequest.writeMultiLineFormat(multiSearchRequest, xContent); request.addParameters(params.asMap()); - request.setEntity(new NByteArrayEntity(source, createContentType(xContent.type()))); + request.setEntity(new NByteArrayEntity(source, createContentType(xContent.mediaType()))); return request; } @@ -549,7 +555,7 @@ static Request multiSearchTemplate(MultiSearchTemplateRequest multiSearchTemplat XContent xContent = REQUEST_BODY_CONTENT_TYPE.xContent(); byte[] source = MultiSearchTemplateRequest.writeMultiLineFormat(multiSearchTemplateRequest, xContent); - request.setEntity(new NByteArrayEntity(source, createContentType(xContent.type()))); + request.setEntity(new NByteArrayEntity(source, createContentType(xContent.mediaType()))); return request; } @@ -867,12 +873,26 @@ static String endpoint(String[] indices, String endpoint, String type) { * * @param xContentType the {@link XContentType} * @return the {@link ContentType} + * + * @deprecated use {@link #createContentType(MediaType)} instead */ + @Deprecated @SuppressForbidden(reason = "Only allowed place to convert a XContentType to a ContentType") public static ContentType createContentType(final XContentType xContentType) { return ContentType.create(xContentType.mediaTypeWithoutParameters(), (Charset) null); } + /** + * Returns a {@link ContentType} from a given {@link XContentType}. + * + * @param mediaType the {@link MediaType} + * @return the {@link ContentType} + */ + @SuppressForbidden(reason = "Only allowed place to convert a XContentType to a ContentType") + public static ContentType createContentType(final MediaType mediaType) { + return ContentType.create(mediaType.mediaTypeWithoutParameters(), (Charset) null); + } + /** * Utility class to help with common parameter names and patterns. Wraps * a {@link Request} and adds the parameters to it directly. diff --git a/client/rest-high-level/src/main/java/org/opensearch/client/indices/CreateIndexRequest.java b/client/rest-high-level/src/main/java/org/opensearch/client/indices/CreateIndexRequest.java index 5bf65a6ea1989..83e148f098f12 100644 --- a/client/rest-high-level/src/main/java/org/opensearch/client/indices/CreateIndexRequest.java +++ b/client/rest-high-level/src/main/java/org/opensearch/client/indices/CreateIndexRequest.java @@ -44,6 +44,7 @@ import org.opensearch.common.bytes.BytesReference; import org.opensearch.common.settings.Settings; import org.opensearch.common.xcontent.DeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.ToXContentObject; import org.opensearch.common.xcontent.XContentBuilder; @@ -64,6 +65,8 @@ /** * A request to create an index. + * + * @opensearch.api */ public class CreateIndexRequest extends TimedRequest implements Validatable, ToXContentObject { static final ParseField MAPPINGS = new ParseField("mappings"); @@ -122,12 +125,23 @@ public CreateIndexRequest settings(Settings settings) { /** * The settings to create the index with (either json or yaml format) + * + * @deprecated use {@link #settings(String source, MediaType mediaType)} instead */ + @Deprecated public CreateIndexRequest settings(String source, XContentType xContentType) { this.settings = Settings.builder().loadFromSource(source, xContentType).build(); return this; } + /** + * The settings to create the index with (either json or yaml format) + */ + public CreateIndexRequest settings(String source, MediaType mediaType) { + this.settings = Settings.builder().loadFromSource(source, mediaType).build(); + return this; + } + /** * Allows to set the settings using a json builder. */ @@ -159,11 +173,26 @@ public XContentType mappingsXContentType() { * * @param source The mapping source * @param xContentType The content type of the source + * + * @deprecated use {@link #mapping(String source, MediaType mediaType)} instead */ + @Deprecated public CreateIndexRequest mapping(String source, XContentType xContentType) { return mapping(new BytesArray(source), xContentType); } + /** + * Adds mapping that will be added when the index gets created. + * + * Note that the definition should *not* be nested under a type name. + * + * @param source The mapping source + * @param mediaType The media type of the source + */ + public CreateIndexRequest mapping(String source, MediaType mediaType) { + return mapping(new BytesArray(source), mediaType); + } + /** * Adds mapping that will be added when the index gets created. * @@ -199,7 +228,10 @@ public CreateIndexRequest mapping(Map source) { * * @param source The mapping source * @param xContentType the content type of the mapping source + * + * @deprecated use {@link #mapping(BytesReference source, MediaType mediaType)} instead */ + @Deprecated public CreateIndexRequest mapping(BytesReference source, XContentType xContentType) { Objects.requireNonNull(xContentType); mappings = source; @@ -207,6 +239,21 @@ public CreateIndexRequest mapping(BytesReference source, XContentType xContentTy return this; } + /** + * Adds mapping that will be added when the index gets created. + * + * Note that the definition should *not* be nested under a type name. + * + * @param source The mapping source + * @param mediaType the content type of the mapping source + */ + public CreateIndexRequest mapping(BytesReference source, MediaType mediaType) { + Objects.requireNonNull(mediaType); + mappings = source; + mappingsXContentType = (XContentType) mediaType; + return this; + } + public Set aliases() { return this.aliases; } @@ -233,7 +280,10 @@ public CreateIndexRequest aliases(XContentBuilder source) { /** * Sets the aliases that will be associated with the index when it gets created + * + * @deprecated use {@link #aliases(String, MediaType)} instead */ + @Deprecated public CreateIndexRequest aliases(String source, XContentType contentType) { return aliases(new BytesArray(source), contentType); } @@ -241,7 +291,24 @@ public CreateIndexRequest aliases(String source, XContentType contentType) { /** * Sets the aliases that will be associated with the index when it gets created */ + public CreateIndexRequest aliases(String source, MediaType mediaType) { + return aliases(new BytesArray(source), mediaType); + } + + /** + * Sets the aliases that will be associated with the index when it gets created + * + * @deprecated use {@link #aliases(BytesReference source, MediaType contentType)} instead + */ + @Deprecated public CreateIndexRequest aliases(BytesReference source, XContentType contentType) { + return aliases(source, (MediaType) contentType); + } + + /** + * Sets the aliases that will be associated with the index when it gets created + */ + public CreateIndexRequest aliases(BytesReference source, MediaType contentType) { // EMPTY is safe here because we never call namedObject try ( XContentParser parser = XContentHelper.createParser( @@ -282,11 +349,23 @@ public CreateIndexRequest aliases(Collection aliases) { * Sets the settings and mappings as a single source. * * Note that the mapping definition should *not* be nested under a type name. + * + * @deprecated use {@link #source(String, MediaType)} instead */ + @Deprecated public CreateIndexRequest source(String source, XContentType xContentType) { return source(new BytesArray(source), xContentType); } + /** + * Sets the settings and mappings as a single source. + * + * Note that the mapping definition should *not* be nested under a type name. + */ + public CreateIndexRequest source(String source, MediaType mediaType) { + return source(new BytesArray(source), mediaType); + } + /** * Sets the settings and mappings as a single source. * @@ -300,13 +379,27 @@ public CreateIndexRequest source(XContentBuilder source) { * Sets the settings and mappings as a single source. * * Note that the mapping definition should *not* be nested under a type name. + * + * @deprecated use {@link #source(BytesReference, MediaType)} instead */ + @Deprecated public CreateIndexRequest source(BytesReference source, XContentType xContentType) { Objects.requireNonNull(xContentType); source(XContentHelper.convertToMap(source, false, xContentType).v2()); return this; } + /** + * Sets the settings and mappings as a single source. + * + * Note that the mapping definition should *not* be nested under a type name. + */ + public CreateIndexRequest source(BytesReference source, MediaType mediaType) { + Objects.requireNonNull(mediaType); + source(XContentHelper.convertToMap(source, false, mediaType).v2()); + return this; + } + /** * Sets the settings and mappings as a single source. * diff --git a/client/rest-high-level/src/main/java/org/opensearch/client/indices/PutIndexTemplateRequest.java b/client/rest-high-level/src/main/java/org/opensearch/client/indices/PutIndexTemplateRequest.java index 5f43ec7f1d0fe..1f28ad10b63bf 100644 --- a/client/rest-high-level/src/main/java/org/opensearch/client/indices/PutIndexTemplateRequest.java +++ b/client/rest-high-level/src/main/java/org/opensearch/client/indices/PutIndexTemplateRequest.java @@ -43,6 +43,7 @@ import org.opensearch.common.bytes.BytesReference; import org.opensearch.common.settings.Settings; import org.opensearch.common.xcontent.DeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.ToXContentFragment; import org.opensearch.common.xcontent.XContentBuilder; @@ -268,9 +269,10 @@ private PutIndexTemplateRequest internalMapping(Map source) { try { XContentBuilder builder = XContentFactory.contentBuilder(XContentType.JSON); builder.map(source); - Objects.requireNonNull(builder.contentType()); + MediaType mediaType = builder.contentType(); + Objects.requireNonNull(mediaType); try { - mappings = new BytesArray(XContentHelper.convertToJson(BytesReference.bytes(builder), false, false, builder.contentType())); + mappings = new BytesArray(XContentHelper.convertToJson(BytesReference.bytes(builder), false, false, mediaType)); return this; } catch (IOException e) { throw new UncheckedIOException("failed to convert source to json", e); @@ -342,7 +344,10 @@ public PutIndexTemplateRequest source(Map templateSource) { /** * The template source definition. + * + * @deprecated use {@link #source(String, MediaType)} instead */ + @Deprecated public PutIndexTemplateRequest source(String templateSource, XContentType xContentType) { return source(XContentHelper.convertToMap(xContentType.xContent(), templateSource, true)); } @@ -350,6 +355,16 @@ public PutIndexTemplateRequest source(String templateSource, XContentType xConte /** * The template source definition. */ + public PutIndexTemplateRequest source(String templateSource, MediaType mediaType) { + return source(XContentHelper.convertToMap(mediaType.xContent(), templateSource, true)); + } + + /** + * The template source definition. + * + * @deprecated use {@link #source(byte[], MediaType)} instead + */ + @Deprecated public PutIndexTemplateRequest source(byte[] source, XContentType xContentType) { return source(source, 0, source.length, xContentType); } @@ -357,6 +372,16 @@ public PutIndexTemplateRequest source(byte[] source, XContentType xContentType) /** * The template source definition. */ + public PutIndexTemplateRequest source(byte[] source, MediaType mediaType) { + return source(source, 0, source.length, mediaType); + } + + /** + * The template source definition. + * + * @deprecated use {@link #source(byte[], int, int, MediaType)} instead + */ + @Deprecated public PutIndexTemplateRequest source(byte[] source, int offset, int length, XContentType xContentType) { return source(new BytesArray(source, offset, length), xContentType); } @@ -364,10 +389,27 @@ public PutIndexTemplateRequest source(byte[] source, int offset, int length, XCo /** * The template source definition. */ + public PutIndexTemplateRequest source(byte[] source, int offset, int length, MediaType mediaType) { + return source(new BytesArray(source, offset, length), mediaType); + } + + /** + * The template source definition. + * + * @deprecated use {@link #source(BytesReference, MediaType)} instead + */ + @Deprecated public PutIndexTemplateRequest source(BytesReference source, XContentType xContentType) { return source(XContentHelper.convertToMap(source, true, xContentType).v2()); } + /** + * The template source definition. + */ + public PutIndexTemplateRequest source(BytesReference source, MediaType mediaType) { + return source(XContentHelper.convertToMap(source, true, mediaType).v2()); + } + public Set aliases() { return this.aliases; } diff --git a/client/rest-high-level/src/main/java/org/opensearch/client/indices/PutMappingRequest.java b/client/rest-high-level/src/main/java/org/opensearch/client/indices/PutMappingRequest.java index c8d5e4c95782a..fc3423ee812fa 100644 --- a/client/rest-high-level/src/main/java/org/opensearch/client/indices/PutMappingRequest.java +++ b/client/rest-high-level/src/main/java/org/opensearch/client/indices/PutMappingRequest.java @@ -38,6 +38,7 @@ import org.opensearch.client.TimedRequest; import org.opensearch.common.bytes.BytesArray; import org.opensearch.common.bytes.BytesReference; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.ToXContent; import org.opensearch.common.xcontent.ToXContentObject; import org.opensearch.common.xcontent.XContentBuilder; @@ -52,6 +53,8 @@ * Put a mapping definition into one or more indices. If an index already contains mappings, * the new mappings will be merged with the existing one. If there are elements that cannot * be merged, the request will be rejected. + * + * @opensearch.api */ public class PutMappingRequest extends TimedRequest implements IndicesRequest, ToXContentObject { @@ -59,7 +62,7 @@ public class PutMappingRequest extends TimedRequest implements IndicesRequest, T private IndicesOptions indicesOptions = IndicesOptions.fromOptions(false, false, true, true); private BytesReference source; - private XContentType xContentType; + private MediaType mediaType; /** * Constructs a new put mapping request against one or more indices. If no indices @@ -96,9 +99,19 @@ public BytesReference source() { /** * The {@link XContentType} of the mapping source. + * + * @deprecated use {@link #mediaType()} instead */ + @Deprecated public XContentType xContentType() { - return xContentType; + return (XContentType) mediaType; + } + + /** + * The {@link XContentType} of the mapping source. + */ + public MediaType mediaType() { + return mediaType; } /** @@ -120,10 +133,24 @@ public PutMappingRequest source(Map mappingSource) { * The mapping source definition. * * Note that the definition should *not* be nested under a type name. + * + * @deprecated use {@link #source(String, MediaType)} instead */ + @Deprecated public PutMappingRequest source(String mappingSource, XContentType xContentType) { this.source = new BytesArray(mappingSource); - this.xContentType = xContentType; + this.mediaType = xContentType; + return this; + } + + /** + * The mapping source definition. + * + * Note that the definition should *not* be nested under a type name. + */ + public PutMappingRequest source(String mappingSource, MediaType mediaType) { + this.source = new BytesArray(mappingSource); + this.mediaType = mediaType; return this; } @@ -134,7 +161,7 @@ public PutMappingRequest source(String mappingSource, XContentType xContentType) */ public PutMappingRequest source(XContentBuilder builder) { this.source = BytesReference.bytes(builder); - this.xContentType = builder.contentType(); + this.mediaType = builder.contentType(); return this; } @@ -142,10 +169,24 @@ public PutMappingRequest source(XContentBuilder builder) { * The mapping source definition. * * Note that the definition should *not* be nested under a type name. + * + * @deprecated use {@link #source(BytesReference, MediaType)} instead */ + @Deprecated public PutMappingRequest source(BytesReference source, XContentType xContentType) { this.source = source; - this.xContentType = xContentType; + this.mediaType = xContentType; + return this; + } + + /** + * The mapping source definition. + * + * Note that the definition should *not* be nested under a type name. + */ + public PutMappingRequest source(BytesReference source, MediaType mediaType) { + this.source = source; + this.mediaType = mediaType; return this; } @@ -153,7 +194,7 @@ public PutMappingRequest source(BytesReference source, XContentType xContentType public XContentBuilder toXContent(XContentBuilder builder, ToXContent.Params params) throws IOException { if (source != null) { try (InputStream stream = source.streamInput()) { - builder.rawValue(stream, xContentType); + builder.rawValue(stream, mediaType); } } else { builder.startObject().endObject(); diff --git a/client/rest-high-level/src/test/java/org/opensearch/client/indices/PutMappingRequestTests.java b/client/rest-high-level/src/test/java/org/opensearch/client/indices/PutMappingRequestTests.java index 6065be82ddb22..877d3cd77687d 100644 --- a/client/rest-high-level/src/test/java/org/opensearch/client/indices/PutMappingRequestTests.java +++ b/client/rest-high-level/src/test/java/org/opensearch/client/indices/PutMappingRequestTests.java @@ -74,8 +74,8 @@ protected boolean supportsUnknownFields() { protected void assertEqualInstances(PutMappingRequest expected, PutMappingRequest actual) { if (actual.source() != null) { try ( - XContentParser expectedJson = createParser(expected.xContentType().xContent(), expected.source()); - XContentParser actualJson = createParser(actual.xContentType().xContent(), actual.source()) + XContentParser expectedJson = createParser(expected.mediaType().xContent(), expected.source()); + XContentParser actualJson = createParser(actual.mediaType().xContent(), actual.source()) ) { assertEquals(expectedJson.mapOrdered(), actualJson.mapOrdered()); } catch (IOException e) { diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/MediaType.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/MediaType.java index 3fad89152cc45..f38457b5ffd4c 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/MediaType.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/MediaType.java @@ -63,5 +63,11 @@ default String typeWithSubtype() { return type() + "/" + subtype(); } + default String mediaType() { + return mediaTypeWithoutParameters(); + } + + String mediaTypeWithoutParameters(); + XContent xContent(); } diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContent.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContent.java index c8a8aa1a0cfa3..b9fff70ca9058 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContent.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContent.java @@ -46,7 +46,7 @@ public interface XContent { /** * The type this content handles and produces. */ - XContentType type(); + MediaType mediaType(); byte streamSeparator(); diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentBuilder.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentBuilder.java index 7086cdb0fda83..7f4878d6336d0 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentBuilder.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentBuilder.java @@ -995,20 +995,42 @@ public XContentBuilder rawField(String name, InputStream value) throws IOExcepti /** * Writes a raw field with the value taken from the bytes in the stream + * + * @deprecated use {@link #rawField(String, InputStream, MediaType)} instead */ + @Deprecated public XContentBuilder rawField(String name, InputStream value, XContentType contentType) throws IOException { generator.writeRawField(name, value, contentType); return this; } + /** + * Writes a raw field with the value taken from the bytes in the stream + */ + public XContentBuilder rawField(String name, InputStream value, MediaType mediaType) throws IOException { + generator.writeRawField(name, value, mediaType); + return this; + } + /** * Writes a value with the source coming directly from the bytes in the stream + * + * @deprecated use {@link #rawValue(InputStream, MediaType)} instead */ + @Deprecated public XContentBuilder rawValue(InputStream stream, XContentType contentType) throws IOException { generator.writeRawValue(stream, contentType); return this; } + /** + * Writes a value with the source coming directly from the bytes in the stream + */ + public XContentBuilder rawValue(InputStream stream, MediaType contentType) throws IOException { + generator.writeRawValue(stream, contentType); + return this; + } + public XContentBuilder copyCurrentStructure(XContentParser parser) throws IOException { generator.copyCurrentStructure(parser); return this; diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentFactory.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentFactory.java index 63b1ef6af752d..676c9618ba9f5 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentFactory.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentFactory.java @@ -141,7 +141,7 @@ public static XContentBuilder contentBuilder(XContentType type) throws IOExcepti /** * Returns the {@link org.opensearch.common.xcontent.XContent} for the provided content type. */ - public static XContent xContent(XContentType type) { + public static XContent xContent(MediaType type) { if (type == null) { throw new IllegalArgumentException("Cannot get xcontent for unknown type"); } diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentGenerator.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentGenerator.java index b0dacb3826be3..c13a3c7fd283c 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentGenerator.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentGenerator.java @@ -116,14 +116,28 @@ public interface XContentGenerator extends Closeable, Flushable { /** * Writes a raw field with the value taken from the bytes in the stream + * @deprecated use {@link #writeRawField(String, InputStream, MediaType)} instead */ + @Deprecated void writeRawField(String name, InputStream value, XContentType xContentType) throws IOException; + /** + * Writes a raw field with the value taken from the bytes in the stream + */ + void writeRawField(String name, InputStream value, MediaType mediaType) throws IOException; + /** * Writes a raw value taken from the bytes in the stream + * @deprecated use {@link #writeRawValue(InputStream, MediaType)} instead */ + @Deprecated void writeRawValue(InputStream value, XContentType xContentType) throws IOException; + /** + * Writes a raw value taken from the bytes in the stream + */ + void writeRawValue(InputStream value, MediaType mediaType) throws IOException; + void copyCurrentStructure(XContentParser parser) throws IOException; default void copyCurrentEvent(XContentParser parser) throws IOException { diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentType.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentType.java index 32283698beaf8..d93df5b05be4a 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentType.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/XContentType.java @@ -186,12 +186,6 @@ public int index() { return index; } - public String mediaType() { - return mediaTypeWithoutParameters(); - } - - public abstract String mediaTypeWithoutParameters(); - @Override public String type() { return "application"; diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/cbor/CborXContent.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/cbor/CborXContent.java index 674b6566bdec0..5b1a064ef5ee1 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/cbor/CborXContent.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/cbor/CborXContent.java @@ -37,6 +37,7 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.dataformat.cbor.CBORFactory; import org.opensearch.common.xcontent.DeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.XContent; import org.opensearch.common.xcontent.XContentBuilder; @@ -75,7 +76,7 @@ public static XContentBuilder contentBuilder() throws IOException { private CborXContent() {} @Override - public XContentType type() { + public MediaType mediaType() { return XContentType.CBOR; } diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/json/JsonXContent.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/json/JsonXContent.java index a7872904b1126..6e084f6a8e58c 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/json/JsonXContent.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/json/JsonXContent.java @@ -37,6 +37,7 @@ import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParser; import org.opensearch.common.xcontent.DeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.XContent; import org.opensearch.common.xcontent.XContentBuilder; @@ -77,7 +78,7 @@ public static XContentBuilder contentBuilder() throws IOException { private JsonXContent() {} @Override - public XContentType type() { + public MediaType mediaType() { return XContentType.JSON; } diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/json/JsonXContentGenerator.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/json/JsonXContentGenerator.java index b972f52c57201..88853f5bc1e61 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/json/JsonXContentGenerator.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/json/JsonXContentGenerator.java @@ -42,6 +42,7 @@ import com.fasterxml.jackson.core.util.DefaultPrettyPrinter; import com.fasterxml.jackson.core.util.JsonGeneratorDelegate; import org.opensearch.common.xcontent.DeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.XContent; import org.opensearch.common.xcontent.XContentFactory; @@ -345,6 +346,11 @@ public void writeRawField(String name, InputStream content) throws IOException { writeRawField(name, content, contentType); } + /** + * Writes a raw field with the value taken from the bytes in the stream + * @deprecated use {@link #writeRawField(String, InputStream, MediaType)} instead + */ + @Deprecated @Override public void writeRawField(String name, InputStream content, XContentType contentType) throws IOException { if (mayWriteRawData(contentType) == false) { @@ -368,6 +374,38 @@ public void writeRawField(String name, InputStream content, XContentType content } } + /** + * Writes a raw field with the value taken from the bytes in the stream + */ + @Override + public void writeRawField(String name, InputStream content, MediaType mediaType) throws IOException { + if (mayWriteRawData(mediaType) == false) { + // EMPTY is safe here because we never call namedObject when writing raw data + try ( + XContentParser parser = XContentFactory.xContent(mediaType) + // It's okay to pass the throwing deprecation handler + // because we should not be writing raw fields when + // generating JSON + .createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, content) + ) { + parser.nextToken(); + writeFieldName(name); + copyCurrentStructure(parser); + } + } else { + writeStartRaw(name); + flush(); + Streams.copy(content, os); + writeEndRaw(); + } + } + + /** + * Writes the raw value to the stream + * + * @deprecated use {@link #writeRawValue(InputStream, MediaType)} instead + */ + @Deprecated @Override public void writeRawValue(InputStream stream, XContentType xContentType) throws IOException { if (mayWriteRawData(xContentType) == false) { @@ -383,6 +421,30 @@ public void writeRawValue(InputStream stream, XContentType xContentType) throws } } + /** + * Writes the raw value to the stream + */ + @Override + public void writeRawValue(InputStream stream, MediaType mediaType) throws IOException { + if (mayWriteRawData(mediaType) == false) { + copyRawValue(stream, mediaType.xContent()); + } else { + if (generator.getOutputContext().getCurrentName() != null) { + // If we've just started a field we'll need to add the separator + generator.writeRaw(':'); + } + flush(); + Streams.copy(stream, os, false); + writeEndRaw(); + } + } + + /** + * possibly copy the whole structure to correctly filter + * + * @deprecated use {@link #mayWriteRawData(MediaType)} instead + */ + @Deprecated private boolean mayWriteRawData(XContentType contentType) { // When the current generator is filtered (ie filter != null) // or the content is in a different format than the current generator, @@ -391,6 +453,17 @@ private boolean mayWriteRawData(XContentType contentType) { return supportsRawWrites() && isFiltered() == false && contentType == contentType() && prettyPrint == false; } + /** + * possibly copy the whole structure to correctly filter + */ + private boolean mayWriteRawData(MediaType contentType) { + // When the current generator is filtered (ie filter != null) + // or the content is in a different format than the current generator, + // we need to copy the whole structure so that it will be correctly + // filtered or converted + return supportsRawWrites() && isFiltered() == false && contentType == contentType() && prettyPrint == false; + } + /** Whether this generator supports writing raw data directly */ protected boolean supportsRawWrites() { return true; diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/smile/SmileXContent.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/smile/SmileXContent.java index 82925c5f84f9c..541c81eb1a364 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/smile/SmileXContent.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/smile/SmileXContent.java @@ -38,6 +38,7 @@ import com.fasterxml.jackson.dataformat.smile.SmileFactory; import com.fasterxml.jackson.dataformat.smile.SmileGenerator; import org.opensearch.common.xcontent.DeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.XContent; import org.opensearch.common.xcontent.XContentBuilder; @@ -77,7 +78,7 @@ public static XContentBuilder contentBuilder() throws IOException { private SmileXContent() {} @Override - public XContentType type() { + public MediaType mediaType() { return XContentType.SMILE; } diff --git a/libs/x-content/src/main/java/org/opensearch/common/xcontent/yaml/YamlXContent.java b/libs/x-content/src/main/java/org/opensearch/common/xcontent/yaml/YamlXContent.java index 8ebdeca71c0ce..0821ff09522c6 100644 --- a/libs/x-content/src/main/java/org/opensearch/common/xcontent/yaml/YamlXContent.java +++ b/libs/x-content/src/main/java/org/opensearch/common/xcontent/yaml/YamlXContent.java @@ -36,6 +36,7 @@ import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; import org.opensearch.common.xcontent.DeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.XContent; import org.opensearch.common.xcontent.XContentBuilder; @@ -70,7 +71,7 @@ public static XContentBuilder contentBuilder() throws IOException { private YamlXContent() {} @Override - public XContentType type() { + public MediaType mediaType() { return XContentType.YAML; } diff --git a/server/src/main/java/org/opensearch/action/admin/indices/create/CreateIndexRequest.java b/server/src/main/java/org/opensearch/action/admin/indices/create/CreateIndexRequest.java index 95837d82be7ac..33cf7fcd5e779 100644 --- a/server/src/main/java/org/opensearch/action/admin/indices/create/CreateIndexRequest.java +++ b/server/src/main/java/org/opensearch/action/admin/indices/create/CreateIndexRequest.java @@ -52,6 +52,7 @@ import org.opensearch.common.settings.Settings; import org.opensearch.common.xcontent.DeprecationHandler; import org.opensearch.common.xcontent.LoggingDeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.XContentBuilder; import org.opensearch.common.xcontent.XContentFactory; @@ -212,12 +213,23 @@ public CreateIndexRequest settings(Settings settings) { /** * The settings to create the index with (either json or yaml format) + * + * @deprecated use {@link #settings(String source, MediaType mediaType)} instead */ + @Deprecated public CreateIndexRequest settings(String source, XContentType xContentType) { this.settings = Settings.builder().loadFromSource(source, xContentType).build(); return this; } + /** + * The settings to create the index with (either json or yaml format) + */ + public CreateIndexRequest settings(String source, MediaType mediaType) { + this.settings = Settings.builder().loadFromSource(source, mediaType).build(); + return this; + } + /** * Allows to set the settings using a json builder. */ @@ -252,23 +264,55 @@ public CreateIndexRequest mapping(String mapping) { * * @param source The mapping source * @param xContentType The content type of the source + * + * @deprecated use {@link #mapping(String source, MediaType mediaType)} instead */ + @Deprecated public CreateIndexRequest mapping(String source, XContentType xContentType) { return mapping(new BytesArray(source), xContentType); } + /** + * Adds mapping that will be added when the index gets created. + * + * Note that the definition should *not* be nested under a type name. + * + * @param source The mapping source + * @param mediaType The media type of the source + */ + public CreateIndexRequest mapping(String source, MediaType mediaType) { + return mapping(new BytesArray(source), mediaType); + } + /** * Adds mapping that will be added when the index gets created. * * @param source The mapping source * @param xContentType the content type of the mapping source + * + * @deprecated use {@link #mapping(BytesReference source, MediaType mediaType)} instead */ + @Deprecated private CreateIndexRequest mapping(BytesReference source, XContentType xContentType) { Objects.requireNonNull(xContentType); Map mappingAsMap = XContentHelper.convertToMap(source, false, xContentType).v2(); return mapping(MapperService.SINGLE_MAPPING_NAME, mappingAsMap); } + /** + * Adds mapping that will be added when the index gets created. + * + * Note that the definition should *not* be nested under a type name. + * + * @param source The mapping source + * @param mediaType The media type of the source + */ + public CreateIndexRequest mapping(BytesReference source, MediaType mediaType) { + Objects.requireNonNull(mediaType); + Map mappingAsMap = XContentHelper.convertToMap(source, false, mediaType).v2(); + return mapping(MapperService.SINGLE_MAPPING_NAME, mappingAsMap); + } + /** * Adds mapping that will be added when the index gets created. * @@ -383,11 +427,23 @@ public CreateIndexRequest alias(Alias alias) { /** * Sets the settings and mappings as a single source. + * + * @deprecated use {@link #source(String, MediaType)} instead */ + @Deprecated public CreateIndexRequest source(String source, XContentType xContentType) { return source(new BytesArray(source), xContentType); } + /** + * Sets the settings and mappings as a single source. + * + * Note that the mapping definition should *not* be nested under a type name. + */ + public CreateIndexRequest source(String source, MediaType mediaType) { + return source(new BytesArray(source), mediaType); + } + /** * Sets the settings and mappings as a single source. */ @@ -397,14 +453,29 @@ public CreateIndexRequest source(XContentBuilder source) { /** * Sets the settings and mappings as a single source. + * + * @deprecated use {@link #source(byte[], MediaType mediaType)} instead */ + @Deprecated public CreateIndexRequest source(byte[] source, XContentType xContentType) { return source(source, 0, source.length, xContentType); } /** * Sets the settings and mappings as a single source. + * + * Note that the mapping definition should *not* be nested under a type name. + */ + public CreateIndexRequest source(byte[] source, MediaType mediaType) { + return source(source, 0, source.length, mediaType); + } + + /** + * Sets the settings and mappings as a single source. + * + * @deprecated use {@link #source(byte[], int, int, MediaType)} instead */ + @Deprecated public CreateIndexRequest source(byte[] source, int offset, int length, XContentType xContentType) { return source(new BytesArray(source, offset, length), xContentType); } @@ -412,12 +483,31 @@ public CreateIndexRequest source(byte[] source, int offset, int length, XContent /** * Sets the settings and mappings as a single source. */ + public CreateIndexRequest source(byte[] source, int offset, int length, MediaType mediaType) { + return source(new BytesArray(source, offset, length), mediaType); + } + + /** + * Sets the settings and mappings as a single source. + * + * @deprecated use {@link #source(BytesReference, MediaType)} instead + */ + @Deprecated public CreateIndexRequest source(BytesReference source, XContentType xContentType) { Objects.requireNonNull(xContentType); source(XContentHelper.convertToMap(source, false, xContentType).v2(), LoggingDeprecationHandler.INSTANCE); return this; } + /** + * Sets the settings and mappings as a single source. + */ + public CreateIndexRequest source(BytesReference source, MediaType mediaType) { + Objects.requireNonNull(mediaType); + source(XContentHelper.convertToMap(source, false, mediaType).v2(), LoggingDeprecationHandler.INSTANCE); + return this; + } + /** * Sets the settings and mappings as a single source. */ diff --git a/server/src/main/java/org/opensearch/action/ingest/PutPipelineRequest.java b/server/src/main/java/org/opensearch/action/ingest/PutPipelineRequest.java index d5fbaa46810f7..63a9c4266d334 100644 --- a/server/src/main/java/org/opensearch/action/ingest/PutPipelineRequest.java +++ b/server/src/main/java/org/opensearch/action/ingest/PutPipelineRequest.java @@ -37,6 +37,7 @@ import org.opensearch.common.bytes.BytesReference; import org.opensearch.common.io.stream.StreamInput; import org.opensearch.common.io.stream.StreamOutput; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.ToXContentObject; import org.opensearch.common.xcontent.XContentBuilder; import org.opensearch.common.xcontent.XContentType; @@ -57,13 +58,28 @@ public class PutPipelineRequest extends AcknowledgedRequest /** * Create a new pipeline request with the id and source along with the content type of the source + * + * @deprecated use {@link #PutPipelineRequest(String, BytesReference, MediaType)} instead */ + @Deprecated public PutPipelineRequest(String id, BytesReference source, XContentType xContentType) { this.id = Objects.requireNonNull(id); this.source = Objects.requireNonNull(source); this.xContentType = Objects.requireNonNull(xContentType); } + /** + * Create a new pipeline request with the id and source along with the content type of the source + */ + public PutPipelineRequest(String id, BytesReference source, MediaType mediaType) { + this.id = Objects.requireNonNull(id); + this.source = Objects.requireNonNull(source); + if (mediaType instanceof XContentType == false) { + throw new IllegalArgumentException("PutPipelineRequest found unsupported media type [" + mediaType.getClass().getName() + "]"); + } + this.xContentType = (XContentType) Objects.requireNonNull(mediaType); + } + public PutPipelineRequest(StreamInput in) throws IOException { super(in); id = in.readString(); diff --git a/server/src/main/java/org/opensearch/common/settings/Settings.java b/server/src/main/java/org/opensearch/common/settings/Settings.java index 9e19134f3cfa0..3e5f30f82512a 100644 --- a/server/src/main/java/org/opensearch/common/settings/Settings.java +++ b/server/src/main/java/org/opensearch/common/settings/Settings.java @@ -49,6 +49,7 @@ import org.opensearch.common.unit.TimeValue; import org.opensearch.common.xcontent.DeprecationHandler; import org.opensearch.common.xcontent.LoggingDeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.ToXContentFragment; import org.opensearch.common.xcontent.XContentBuilder; @@ -1090,7 +1091,7 @@ public Builder loadFromMap(Map map) { /** * Loads settings from the actual string content that represents them using {@link #fromXContent(XContentParser)} */ - public Builder loadFromSource(String source, XContentType xContentType) { + public Builder loadFromSource(String source, MediaType xContentType) { try ( XContentParser parser = XContentFactory.xContent(xContentType) .createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, source) diff --git a/server/src/main/java/org/opensearch/common/xcontent/XContentHelper.java b/server/src/main/java/org/opensearch/common/xcontent/XContentHelper.java index e4b35d6ee2753..bfc85ce82da74 100644 --- a/server/src/main/java/org/opensearch/common/xcontent/XContentHelper.java +++ b/server/src/main/java/org/opensearch/common/xcontent/XContentHelper.java @@ -61,7 +61,7 @@ public class XContentHelper { /** * Creates a parser based on the bytes provided - * @deprecated use {@link #createParser(NamedXContentRegistry, DeprecationHandler, BytesReference, XContentType)} + * @deprecated use {@link #createParser(NamedXContentRegistry, DeprecationHandler, BytesReference, MediaType)} * to avoid content type auto-detection */ @Deprecated @@ -96,9 +96,9 @@ public static XContentParser createParser( NamedXContentRegistry xContentRegistry, DeprecationHandler deprecationHandler, BytesReference bytes, - XContentType xContentType + MediaType mediaType ) throws IOException { - Objects.requireNonNull(xContentType); + Objects.requireNonNull(mediaType); Compressor compressor = CompressorFactory.compressor(bytes); if (compressor != null) { InputStream compressedInput = null; @@ -107,7 +107,7 @@ public static XContentParser createParser( if (compressedInput.markSupported() == false) { compressedInput = new BufferedInputStream(compressedInput); } - return XContentFactory.xContent(xContentType).createParser(xContentRegistry, deprecationHandler, compressedInput); + return XContentFactory.xContent(mediaType).createParser(xContentRegistry, deprecationHandler, compressedInput); } catch (Exception e) { if (compressedInput != null) compressedInput.close(); throw e; @@ -115,16 +115,16 @@ public static XContentParser createParser( } else { if (bytes instanceof BytesArray) { final BytesArray array = (BytesArray) bytes; - return xContentType.xContent() + return mediaType.xContent() .createParser(xContentRegistry, deprecationHandler, array.array(), array.offset(), array.length()); } - return xContentType.xContent().createParser(xContentRegistry, deprecationHandler, bytes.streamInput()); + return mediaType.xContent().createParser(xContentRegistry, deprecationHandler, bytes.streamInput()); } } /** * Converts the given bytes into a map that is optionally ordered. - * @deprecated this method relies on auto-detection of content type. Use {@link #convertToMap(BytesReference, boolean, XContentType)} + * @deprecated this method relies on auto-detection of content type. Use {@link #convertToMap(BytesReference, boolean, MediaType)} * instead with the proper {@link XContentType} */ @Deprecated @@ -135,11 +135,29 @@ public static Tuple> convertToMap(BytesReferen /** * Converts the given bytes into a map that is optionally ordered. The provided {@link XContentType} must be non-null. + * + * @deprecated use {@link #convertToMap(BytesReference, boolean, MediaType)} instead */ - public static Tuple> convertToMap(BytesReference bytes, boolean ordered, XContentType xContentType) - throws OpenSearchParseException { + @Deprecated + public static Tuple> convertToMap(BytesReference bytes, boolean ordered, XContentType xContentType) { + if (Objects.isNull(xContentType) == false && xContentType instanceof XContentType == false) { + throw new IllegalArgumentException( + "XContentHelper.convertToMap does not support media type [" + xContentType.getClass().getName() + "]" + ); + } + return (Tuple>) convertToMap(bytes, ordered, (MediaType) xContentType); + } + + /** + * Converts the given bytes into a map that is optionally ordered. The provided {@link XContentType} must be non-null. + */ + public static Tuple> convertToMap( + BytesReference bytes, + boolean ordered, + MediaType xContentType + ) throws OpenSearchParseException { try { - final XContentType contentType; + final MediaType contentType; InputStream input; Compressor compressor = CompressorFactory.compressor(bytes); if (compressor != null) { @@ -243,7 +261,7 @@ public static String convertToJson(BytesReference bytes, boolean reformatJson, b return convertToJson(bytes, reformatJson, prettyPrint, XContentFactory.xContentType(bytes.toBytesRef().bytes)); } - public static String convertToJson(BytesReference bytes, boolean reformatJson, XContentType xContentType) throws IOException { + public static String convertToJson(BytesReference bytes, boolean reformatJson, MediaType xContentType) throws IOException { return convertToJson(bytes, reformatJson, false, xContentType); } @@ -260,10 +278,24 @@ public static String stripWhitespace(String json) throws IOException { return convertToJson(new BytesArray(json), true, XContentType.JSON); } + /** + * Converts the XContentType to a json string + * + * @deprecated use {@link #convertToJson(BytesReference, boolean, boolean, MediaType)} instead + */ + @Deprecated public static String convertToJson(BytesReference bytes, boolean reformatJson, boolean prettyPrint, XContentType xContentType) throws IOException { - Objects.requireNonNull(xContentType); - if (xContentType == XContentType.JSON && !reformatJson) { + return convertToJson(bytes, reformatJson, prettyPrint, (MediaType) xContentType); + } + + /** + * Converts the given {@link MediaType} to a json string + */ + public static String convertToJson(BytesReference bytes, boolean reformatJson, boolean prettyPrint, MediaType mediaType) + throws IOException { + Objects.requireNonNull(mediaType); + if (mediaType == XContentType.JSON && !reformatJson) { return bytes.utf8ToString(); } @@ -271,7 +303,7 @@ public static String convertToJson(BytesReference bytes, boolean reformatJson, b if (bytes instanceof BytesArray) { final BytesArray array = (BytesArray) bytes; try ( - XContentParser parser = XContentFactory.xContent(xContentType) + XContentParser parser = XContentFactory.xContent(mediaType) .createParser( NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, @@ -285,7 +317,7 @@ public static String convertToJson(BytesReference bytes, boolean reformatJson, b } else { try ( InputStream stream = bytes.streamInput(); - XContentParser parser = XContentFactory.xContent(xContentType) + XContentParser parser = XContentFactory.xContent(mediaType) .createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, stream) ) { return toJsonString(prettyPrint, parser); @@ -465,7 +497,10 @@ public static BytesReference toXContent(ToXContent toXContent, XContentType xCon * Returns the bytes that represent the XContent output of the provided {@link ToXContent} object, using the provided * {@link XContentType}. Wraps the output into a new anonymous object according to the value returned * by the {@link ToXContent#isFragment()} method returns. + * + * @deprecated use {@link #toXContent(ToXContent, MediaType, Params, boolean)} instead */ + @Deprecated public static BytesReference toXContent(ToXContent toXContent, XContentType xContentType, Params params, boolean humanReadable) throws IOException { try (XContentBuilder builder = XContentBuilder.builder(xContentType.xContent())) { @@ -481,6 +516,26 @@ public static BytesReference toXContent(ToXContent toXContent, XContentType xCon } } + /** + * Returns the bytes that represent the XContent output of the provided {@link ToXContent} object, using the provided + * {@link XContentType}. Wraps the output into a new anonymous object according to the value returned + * by the {@link ToXContent#isFragment()} method returns. + */ + public static BytesReference toXContent(ToXContent toXContent, MediaType mediaType, Params params, boolean humanReadable) + throws IOException { + try (XContentBuilder builder = XContentBuilder.builder(mediaType.xContent())) { + builder.humanReadable(humanReadable); + if (toXContent.isFragment()) { + builder.startObject(); + } + toXContent.toXContent(builder, params); + if (toXContent.isFragment()) { + builder.endObject(); + } + return BytesReference.bytes(builder); + } + } + /** * Guesses the content type based on the provided bytes. * diff --git a/server/src/main/java/org/opensearch/index/reindex/ReindexRequest.java b/server/src/main/java/org/opensearch/index/reindex/ReindexRequest.java index b444757b85951..f27e289ba13b5 100644 --- a/server/src/main/java/org/opensearch/index/reindex/ReindexRequest.java +++ b/server/src/main/java/org/opensearch/index/reindex/ReindexRequest.java @@ -307,7 +307,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws builder.startObject("source"); if (remoteInfo != null) { builder.field("remote", remoteInfo); - builder.rawField("query", remoteInfo.getQuery().streamInput(), RemoteInfo.QUERY_CONTENT_TYPE.type()); + builder.rawField("query", remoteInfo.getQuery().streamInput(), RemoteInfo.QUERY_CONTENT_TYPE.mediaType()); } builder.array("index", getSearchRequest().indices()); getSearchRequest().source().innerToXContent(builder, params); diff --git a/server/src/test/java/org/opensearch/OpenSearchExceptionTests.java b/server/src/test/java/org/opensearch/OpenSearchExceptionTests.java index 6e328ccef517a..b3a6fc93ea601 100644 --- a/server/src/test/java/org/opensearch/OpenSearchExceptionTests.java +++ b/server/src/test/java/org/opensearch/OpenSearchExceptionTests.java @@ -742,7 +742,7 @@ public void testThrowableToAndFromXContent() throws IOException { BytesReference throwableBytes = toShuffledXContent((builder, params) -> { OpenSearchException.generateThrowableXContent(builder, params, throwable); return builder; - }, xContent.type(), ToXContent.EMPTY_PARAMS, randomBoolean()); + }, xContent.mediaType(), ToXContent.EMPTY_PARAMS, randomBoolean()); OpenSearchException parsedException; try (XContentParser parser = createParser(xContent, throwableBytes)) { @@ -774,7 +774,7 @@ public void testUnknownFailureToAndFromXContent() throws IOException { // Prints a null failure using generateFailureXContent() OpenSearchException.generateFailureXContent(builder, params, null, randomBoolean()); return builder; - }, xContent.type(), ToXContent.EMPTY_PARAMS, randomBoolean()); + }, xContent.mediaType(), ToXContent.EMPTY_PARAMS, randomBoolean()); OpenSearchException parsedFailure; try (XContentParser parser = createParser(xContent, failureBytes)) { @@ -798,7 +798,7 @@ public void testFailureToAndFromXContentWithNoDetails() throws IOException { BytesReference failureBytes = toShuffledXContent((builder, params) -> { OpenSearchException.generateFailureXContent(builder, params, failure, false); return builder; - }, xContent.type(), ToXContent.EMPTY_PARAMS, randomBoolean()); + }, xContent.mediaType(), ToXContent.EMPTY_PARAMS, randomBoolean()); try (XContentParser parser = createParser(xContent, failureBytes)) { failureBytes = BytesReference.bytes(shuffleXContent(parser, randomBoolean())); @@ -952,7 +952,7 @@ public void testFailureToAndFromXContentWithDetails() throws IOException { BytesReference failureBytes = toShuffledXContent((builder, params) -> { OpenSearchException.generateFailureXContent(builder, params, finalFailure, true); return builder; - }, xContent.type(), ToXContent.EMPTY_PARAMS, randomBoolean()); + }, xContent.mediaType(), ToXContent.EMPTY_PARAMS, randomBoolean()); try (XContentParser parser = createParser(xContent, failureBytes)) { failureBytes = BytesReference.bytes(shuffleXContent(parser, randomBoolean())); diff --git a/server/src/test/java/org/opensearch/action/search/SearchPhaseExecutionExceptionTests.java b/server/src/test/java/org/opensearch/action/search/SearchPhaseExecutionExceptionTests.java index 7731e2d8ede45..aad528e9b007e 100644 --- a/server/src/test/java/org/opensearch/action/search/SearchPhaseExecutionExceptionTests.java +++ b/server/src/test/java/org/opensearch/action/search/SearchPhaseExecutionExceptionTests.java @@ -134,7 +134,7 @@ public void testToAndFromXContent() throws IOException { final String phase = randomFrom("query", "search", "other"); SearchPhaseExecutionException actual = new SearchPhaseExecutionException(phase, "unexpected failures", shardSearchFailures); - BytesReference exceptionBytes = toShuffledXContent(actual, xContent.type(), ToXContent.EMPTY_PARAMS, randomBoolean()); + BytesReference exceptionBytes = toShuffledXContent(actual, xContent.mediaType(), ToXContent.EMPTY_PARAMS, randomBoolean()); OpenSearchException parsedException; try (XContentParser parser = createParser(xContent, exceptionBytes)) { diff --git a/server/src/test/java/org/opensearch/common/xcontent/BaseXContentTestCase.java b/server/src/test/java/org/opensearch/common/xcontent/BaseXContentTestCase.java index f8b0ec2346abb..f6324c1232444 100644 --- a/server/src/test/java/org/opensearch/common/xcontent/BaseXContentTestCase.java +++ b/server/src/test/java/org/opensearch/common/xcontent/BaseXContentTestCase.java @@ -941,7 +941,7 @@ void doTestRawValue(XContent source) throws Exception { os = new ByteArrayOutputStream(); try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) { - generator.writeRawValue(new BytesArray(rawData).streamInput(), source.type()); + generator.writeRawValue(new BytesArray(rawData).streamInput(), source.mediaType()); } try ( @@ -966,7 +966,7 @@ public void close() { try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) { generator.writeStartObject(); generator.writeFieldName("test"); - generator.writeRawValue(new BytesArray(rawData).streamInput(), source.type()); + generator.writeRawValue(new BytesArray(rawData).streamInput(), source.mediaType()); assertFalse("Generator should not have closed the output stream", closed.get()); generator.writeEndObject(); } diff --git a/test/framework/src/main/java/org/opensearch/test/OpenSearchTestCase.java b/test/framework/src/main/java/org/opensearch/test/OpenSearchTestCase.java index ecf0de521f36a..d4090fdfdfdad 100644 --- a/test/framework/src/main/java/org/opensearch/test/OpenSearchTestCase.java +++ b/test/framework/src/main/java/org/opensearch/test/OpenSearchTestCase.java @@ -94,6 +94,7 @@ import org.opensearch.common.util.concurrent.ThreadContext; import org.opensearch.common.util.set.Sets; import org.opensearch.common.xcontent.LoggingDeprecationHandler; +import org.opensearch.common.xcontent.MediaType; import org.opensearch.common.xcontent.NamedXContentRegistry; import org.opensearch.common.xcontent.ToXContent; import org.opensearch.common.xcontent.XContent; @@ -1237,7 +1238,10 @@ public GeohashGenerator() { * Returns the bytes that represent the XContent output of the provided {@link ToXContent} object, using the provided * {@link XContentType}. Wraps the output into a new anonymous object according to the value returned * by the {@link ToXContent#isFragment()} method returns. Shuffles the keys to make sure that parsing never relies on keys ordering. + * + * @deprecated use {@link #toShuffledXContent(ToXContent, MediaType, ToXContent.Params, boolean, String...)} instead */ + @Deprecated protected final BytesReference toShuffledXContent( ToXContent toXContent, XContentType xContentType, @@ -1253,6 +1257,26 @@ protected final BytesReference toShuffledXContent( } } + /** + * Returns the bytes that represent the XContent output of the provided {@link ToXContent} object, using the provided + * {@link XContentType}. Wraps the output into a new anonymous object according to the value returned + * by the {@link ToXContent#isFragment()} method returns. Shuffles the keys to make sure that parsing never relies on keys ordering. + */ + protected final BytesReference toShuffledXContent( + ToXContent toXContent, + MediaType mediaType, + ToXContent.Params params, + boolean humanReadable, + String... exceptFieldNames + ) throws IOException { + BytesReference bytes = XContentHelper.toXContent(toXContent, mediaType, params, humanReadable); + try (XContentParser parser = createParser(mediaType.xContent(), bytes)) { + try (XContentBuilder builder = shuffleXContent(parser, rarely(), exceptFieldNames)) { + return BytesReference.bytes(builder); + } + } + } + /** * Randomly shuffles the fields inside objects in the {@link XContentBuilder} passed in. * Recursively goes through inner objects and also shuffles them. Exceptions for this