Skip to content

Collect config for XContentParser #79814

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 16 commits into from
Oct 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.support.filtering.FilterPath;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
Expand Down Expand Up @@ -41,8 +41,7 @@ public class FetchSourcePhaseBenchmark {
private FetchSourceContext fetchContext;
private Set<String> includesSet;
private Set<String> excludesSet;
private FilterPath[] includesFilters;
private FilterPath[] excludesFilters;
private XContentParserConfiguration parserConfig;

@Param({ "tiny", "short", "one_4k_field", "one_4m_field" })
private String source;
Expand Down Expand Up @@ -76,8 +75,7 @@ public void setup() throws IOException {
);
includesSet = Set.of(fetchContext.includes());
excludesSet = Set.of(fetchContext.excludes());
includesFilters = FilterPath.compile(Set.of(fetchContext.includes()));
excludesFilters = FilterPath.compile(Set.of(fetchContext.excludes()));
parserConfig = XContentParserConfiguration.EMPTY.withFiltering(includesSet, excludesSet);
}

private BytesReference read300BytesExample() throws IOException {
Expand All @@ -102,16 +100,7 @@ public BytesReference filterObjects() throws IOException {
public BytesReference filterXContentOnParser() throws IOException {
BytesStreamOutput streamOutput = new BytesStreamOutput(Math.min(1024, sourceBytes.length()));
XContentBuilder builder = new XContentBuilder(XContentType.JSON.xContent(), streamOutput);
try (
XContentParser parser = XContentType.JSON.xContent()
.createParser(
NamedXContentRegistry.EMPTY,
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
sourceBytes.streamInput(),
includesFilters,
excludesFilters
)
) {
try (XContentParser parser = XContentType.JSON.xContent().createParser(parserConfig, sourceBytes.streamInput())) {
builder.copyCurrentStructure(parser);
return BytesReference.bytes(builder);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@
import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.lucene.uid.Versions;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.core.RestApiVersion;
import org.elasticsearch.core.TimeValue;
import org.elasticsearch.core.Tuple;
import org.elasticsearch.index.VersionType;
Expand Down Expand Up @@ -1257,17 +1256,16 @@ public void testMultiSearch() throws IOException {
requests.add(searchRequest);
};
MultiSearchRequest.readMultiLineFormat(
new BytesArray(EntityUtils.toByteArray(request.getEntity())),
REQUEST_BODY_CONTENT_TYPE.xContent(),
parserConfig(),
new BytesArray(EntityUtils.toByteArray(request.getEntity())),
consumer,
null,
multiSearchRequest.indicesOptions(),
null,
null,
null,
xContentRegistry(),
true,
RestApiVersion.current()
true
);
assertEquals(requests, multiSearchRequest.requests());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@

package org.elasticsearch.xcontent;

import org.elasticsearch.core.RestApiVersion;
import org.elasticsearch.xcontent.support.filtering.FilterPath;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
Expand Down Expand Up @@ -50,78 +47,67 @@ default XContentGenerator createGenerator(OutputStream os) throws IOException {
/**
* Creates a parser over the provided string content.
*/
XContentParser createParser(NamedXContentRegistry xContentRegistry, DeprecationHandler deprecationHandler, String content)
throws IOException;
XContentParser createParser(XContentParserConfiguration config, String content) throws IOException;

/**
* Creates a parser over the provided string content.
* @deprecated Use {@link #createParser(XContentParserConfiguration, InputStream)}
*/
@Deprecated
default XContentParser createParser(NamedXContentRegistry registry, DeprecationHandler deprecationHandler, String content)
throws IOException {
return createParser(XContentParserConfiguration.EMPTY.withRegistry(registry).withDeprecationHandler(deprecationHandler), content);
}

/**
* Creates a parser over the provided input stream.
*/
XContentParser createParser(NamedXContentRegistry xContentRegistry, DeprecationHandler deprecationHandler, InputStream is)
throws IOException;
XContentParser createParser(XContentParserConfiguration config, InputStream is) throws IOException;

/**
* Creates a parser over the provided input stream.
* @deprecated Use {@link #createParser(XContentParserConfiguration, InputStream)}
*/
XContentParser createParser(
NamedXContentRegistry xContentRegistry,
DeprecationHandler deprecationHandler,
InputStream is,
FilterPath[] includes,
FilterPath[] excludes
) throws IOException;
@Deprecated
default XContentParser createParser(NamedXContentRegistry registry, DeprecationHandler deprecationHandler, InputStream is)
throws IOException {
return createParser(XContentParserConfiguration.EMPTY.withRegistry(registry).withDeprecationHandler(deprecationHandler), is);
}

/**
* Creates a parser over the provided bytes.
*/
XContentParser createParser(NamedXContentRegistry xContentRegistry, DeprecationHandler deprecationHandler, byte[] data)
throws IOException;
default XContentParser createParser(XContentParserConfiguration config, byte[] data) throws IOException {
return createParser(config, data, 0, data.length);
}

/**
* Creates a parser over the provided bytes.
* @deprecated Use {@link #createParser(XContentParserConfiguration, byte[])}
*/
XContentParser createParser(
NamedXContentRegistry xContentRegistry,
DeprecationHandler deprecationHandler,
byte[] data,
int offset,
int length
) throws IOException;
@Deprecated
default XContentParser createParser(NamedXContentRegistry registry, DeprecationHandler deprecationHandler, byte[] data)
throws IOException {
return createParser(XContentParserConfiguration.EMPTY.withRegistry(registry).withDeprecationHandler(deprecationHandler), data);
}

XContentParser createParser(
NamedXContentRegistry xContentRegistry,
DeprecationHandler deprecationHandler,
byte[] data,
int offset,
int length,
FilterPath[] includes,
FilterPath[] excludes
) throws IOException;
/**
* Creates a parser over the provided bytes.
*/
XContentParser createParser(XContentParserConfiguration config, byte[] data, int offset, int length) throws IOException;

/**
* Creates a parser over the provided reader.
*/
XContentParser createParser(NamedXContentRegistry xContentRegistry, DeprecationHandler deprecationHandler, Reader reader)
throws IOException;
XContentParser createParser(XContentParserConfiguration config, Reader reader) throws IOException;

/**
* Creates a parser over the provided input stream and with the indication that a request is using REST compatible API.
*
* @param restApiVersion - indicates if the N-1 or N compatible XContent parsing logic will be used.
* Creates a parser over the provided reader.
* @deprecated Use {@link #createParser(XContentParserConfiguration, Reader)}
*/
XContentParser createParserForCompatibility(
NamedXContentRegistry xContentRegistry,
DeprecationHandler deprecationHandler,
InputStream is,
RestApiVersion restApiVersion
) throws IOException;

XContentParser createParserForCompatibility(
NamedXContentRegistry xContentRegistry,
DeprecationHandler deprecationHandler,
byte[] data,
int offset,
int length,
RestApiVersion restApiVersion
) throws IOException;

@Deprecated
default XContentParser createParser(NamedXContentRegistry registry, DeprecationHandler deprecationHandler, Reader reader)
throws IOException {
return createParser(XContentParserConfiguration.EMPTY.withRegistry(registry).withDeprecationHandler(deprecationHandler), reader);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.xcontent;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.filter.FilteringParserDelegate;

import org.elasticsearch.core.RestApiVersion;
import org.elasticsearch.xcontent.support.filtering.FilterPath;
import org.elasticsearch.xcontent.support.filtering.FilterPathBasedFilter;

import java.util.Set;

/**
* Configuration for {@link XContentParser}.
*/
public class XContentParserConfiguration {
/**
* Creates parsers that don't support {@link XContentParser#namedObject},
* throw an exception when they see deprecated fields, that return the
* {@link RestApiVersion#current() current version} from
* {@link XContentParser#getRestApiVersion}, and do no filtering.
*/
public static final XContentParserConfiguration EMPTY = new XContentParserConfiguration(
NamedXContentRegistry.EMPTY,
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
RestApiVersion.current(),
null,
null
);

final NamedXContentRegistry registry;
final DeprecationHandler deprecationHandler;
final RestApiVersion restApiVersion;
final FilterPath[] includes;
final FilterPath[] excludes;

private XContentParserConfiguration(
NamedXContentRegistry registry,
DeprecationHandler deprecationHandler,
RestApiVersion restApiVersion,
FilterPath[] includes,
FilterPath[] excludes
) {
this.registry = registry;
this.deprecationHandler = deprecationHandler;
this.restApiVersion = restApiVersion;
this.includes = includes;
this.excludes = excludes;
}

/**
* Replace the registry backing {@link XContentParser#namedObject}.
*/
public XContentParserConfiguration withRegistry(NamedXContentRegistry registry) {
return new XContentParserConfiguration(registry, deprecationHandler, restApiVersion, includes, excludes);
}

public NamedXContentRegistry registry() {
return registry;
}

/**
* Replace the behavior of {@link XContentParser} when it encounters
* a deprecated field.
*/
public XContentParserConfiguration withDeprecationHandler(DeprecationHandler deprecationHandler) {
return new XContentParserConfiguration(registry, deprecationHandler, restApiVersion, includes, excludes);
}

public DeprecationHandler deprecationHandler() {
return deprecationHandler;
}

/**
* Replace the {@link XContentParser#getRestApiVersion() claimed}
* {@link RestApiVersion}.
*/
public XContentParserConfiguration withRestApiVersion(RestApiVersion restApiVersion) {
return new XContentParserConfiguration(registry, deprecationHandler, restApiVersion, includes, excludes);
}

public RestApiVersion restApiVersion() {
return restApiVersion;
}

/**
* Replace the configured filtering.
*/
public XContentParserConfiguration withFiltering(Set<String> includes, Set<String> excludes) {
return new XContentParserConfiguration(
registry,
deprecationHandler,
restApiVersion,
FilterPath.compile(includes),
FilterPath.compile(excludes)
);
}

public JsonParser filter(JsonParser parser) {
JsonParser filtered = parser;
if (excludes != null) {
for (FilterPath e : excludes) {
if (e.hasDoubleWildcard()) {
// Fixed in Jackson 2.13 - https://github.com/FasterXML/jackson-core/issues/700
throw new UnsupportedOperationException("double wildcards are not supported in filtered excludes");
}
}
filtered = new FilteringParserDelegate(filtered, new FilterPathBasedFilter(excludes, false), true, true);
}
if (includes != null) {
filtered = new FilteringParserDelegate(filtered, new FilterPathBasedFilter(includes, true), true, true);
}
return filtered;
}
}
Loading