Move x-content implementation to a separate classloader (#83705)

This change isolates the Jackson implementation of x-content parsers and generators to a separate classloader. The code is loaded dynamically upon accessing any x-content functionality.

The x-content implementation is embedded inside the x-content jar, as a hidden set of resource files. These are loaded through a special classloader created to initialize the XContentProvider through service loader. One caveat to this approach is that IDEs will no longer trigger building the x-content implementation when it changes. However, running any test from the command line, or running a full Build in IntelliJ will trigger the directory to be built.

Co-authored-by: ChrisHegarty <christopher.hegarty@elastic.co>
This commit is contained in:
Ryan Ernst 2022-03-07 15:44:59 -08:00 committed by GitHub
parent 37beabcb2e
commit 070fcaa0ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
110 changed files with 1947 additions and 645 deletions

View File

@ -88,7 +88,10 @@ if (providers.systemProperty('idea.active').getOrNull() == 'true') {
tasks.register('buildDependencyArtifacts') {
group = 'ide'
description = 'Builds artifacts needed as dependency for IDE modules'
dependsOn ':client:rest-high-level:shadowJar', ':plugins:repository-hdfs:hadoop-client-api:shadowJar', ':modules:repository-azure:azure-storage-blob:shadowJar'
dependsOn ':client:rest-high-level:shadowJar',
':plugins:repository-hdfs:hadoop-client-api:shadowJar',
':modules:repository-azure:azure-storage-blob:shadowJar',
':libs:elasticsearch-x-content:generateProviderImpl'
}
idea {

View File

@ -14,6 +14,7 @@ import org.gradle.api.artifacts.transform.TransformOutputs;
import org.gradle.api.artifacts.transform.TransformParameters;
import org.gradle.api.file.FileSystemLocation;
import org.gradle.api.logging.Logging;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
@ -57,6 +58,10 @@ public interface UnpackTransform extends TransformAction<UnpackTransform.Paramet
void setTargetDirectory(File targetDirectory);
void setKeepStructureFor(List<String> pattern);
@Input
@Optional
Property<Boolean> getIncludeArtifactName();
}
@PathSensitive(PathSensitivity.NAME_ONLY)
@ -67,6 +72,11 @@ public interface UnpackTransform extends TransformAction<UnpackTransform.Paramet
default void transform(TransformOutputs outputs) {
File archiveFile = getArchiveFile().get().getAsFile();
File extractedDir = outputs.dir(archiveFile.getName());
if (getParameters().getIncludeArtifactName().getOrElse(false)) {
extractedDir = new File(extractedDir, archiveFile.getName());
}
try {
Logging.getLogger(UnpackTransform.class)
.info("Unpacking " + archiveFile.getName() + " using " + getClass().getSimpleName() + ".");

View File

@ -17,6 +17,7 @@ import org.gradle.api.logging.Logging;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Enumeration;
import java.util.function.Function;
@ -39,6 +40,7 @@ public abstract class UnzipTransform implements UnpackTransform {
continue;
}
Path outputPath = targetDir.toPath().resolve(child);
Files.createDirectories(outputPath.getParent());
if (zipEntry.isDirectory()) {
outputPath.toFile().mkdirs();
chmod(outputPath, zipEntry.getUnixMode());

View File

@ -11,7 +11,7 @@ apply plugin: 'elasticsearch.build'
dependencies {
compileOnly project(':distribution:tools:java-version-checker')
compileOnly "org.yaml:snakeyaml:${versions.snakeyaml}"
implementation "org.yaml:snakeyaml:${versions.snakeyaml}"
testImplementation "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
testImplementation "junit:junit:${versions.junit}"
testImplementation "org.hamcrest:hamcrest:${versions.hamcrest}"

View File

@ -22,8 +22,10 @@ configure(subprojects - project('elasticsearch-log4j')) {
dependencies.matching { it instanceof ProjectDependency }.all { ProjectDependency dep ->
Project depProject = dep.dependencyProject
if (depProject != null
&& false == depProject.path.equals(':libs:elasticsearch-x-content')
&& false == depProject.path.equals(':libs:elasticsearch-core')
&& depProject.path.startsWith(':libs')) {
&& depProject.path.startsWith(':libs')
&& depProject.name.startsWith('elasticsearch-')) {
throw new InvalidUserDataException("projects in :libs "
+ "may not depend on other projects libs except "
+ ":libs:elasticsearch-core but "

View File

@ -6,26 +6,46 @@
* Side Public License, v 1.
*/
import org.elasticsearch.gradle.transform.UnzipTransform
import org.gradle.api.internal.artifacts.ArtifactAttributes
import java.util.stream.Collectors
apply plugin: 'elasticsearch.build'
apply plugin: 'elasticsearch.publish'
def isImplAttr = Attribute.of("is.impl", Boolean)
configurations {
providerImpl {
attributes.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE)
attributes.attribute(isImplAttr, true)
}
}
dependencies {
registerTransform(
UnzipTransform.class, transformSpec -> {
transformSpec.getFrom()
.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.JAR_TYPE)
.attribute(isImplAttr, true)
transformSpec.getTo()
.attribute(ArtifactTypeDefinition.ARTIFACT_TYPE_ATTRIBUTE, ArtifactTypeDefinition.DIRECTORY_TYPE)
.attribute(isImplAttr, true)
transformSpec.parameters(parameters -> {
parameters.includeArtifactName.set(true)
})
})
api project(':libs:elasticsearch-core')
api "org.yaml:snakeyaml:${versions.snakeyaml}"
api "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
api "com.fasterxml.jackson.dataformat:jackson-dataformat-smile:${versions.jackson}"
api "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${versions.jackson}"
api "com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:${versions.jackson}"
testImplementation "com.carrotsearch.randomizedtesting:randomizedtesting-runner:${versions.randomizedrunner}"
testImplementation "junit:junit:${versions.junit}"
testImplementation "org.hamcrest:hamcrest:${versions.hamcrest}"
providerImpl project(':libs:elasticsearch-x-content:impl')
testImplementation(project(":test:framework")) {
exclude group: 'org.elasticsearch', module: 'elasticsearch-x-content'
}
}
tasks.named('forbiddenApisMain').configure {
@ -46,4 +66,23 @@ tasks.named("dependencyLicenses").configure {
mapping from: /jackson-.*/, to: 'jackson'
}
tasks.named("jarHell").configure { enabled = false }
File generatedResourcesDir = new File(buildDir, 'generated-resources')
def generateProviderManifest = tasks.register("generateProviderManifest") {
File manifestFile = new File(generatedResourcesDir, "LISTING.TXT")
inputs.property('jars', configurations.providerImpl)
outputs.file(manifestFile)
doLast {
manifestFile.parentFile.mkdirs()
manifestFile.setText(configurations.providerImpl.files.stream()
.map(f -> f.name).collect(Collectors.joining('\n')), 'UTF-8')
}
}
def generateProviderImpl = tasks.register("generateProviderImpl", Copy) {
destinationDir = new File(generatedResourcesDir, "impl")
into("IMPL-JARS/x-content") {
from(configurations.providerImpl)
from(generateProviderManifest)
}
}
sourceSets.main.output.dir(generateProviderImpl)

View File

@ -0,0 +1,46 @@
/*
* 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.
*/
apply plugin: 'elasticsearch.java'
archivesBaseName = "x-content-impl"
dependencies {
compileOnly project(':libs:elasticsearch-core')
compileOnly project(':libs:elasticsearch-x-content')
implementation "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-smile:${versions.jackson}"
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-yaml:${versions.jackson}"
implementation "com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:${versions.jackson}"
implementation "org.yaml:snakeyaml:${versions.snakeyaml}"
testImplementation(project(":test:framework")) {
exclude group: 'org.elasticsearch', module: 'elasticsearch-x-content'
}
}
tasks.named('forbiddenApisMain').configure {
// x-content does not depend on server
// TODO: Need to decide how we want to handle for forbidden signatures with the changes to core
replaceSignatureFiles 'jdk-signatures'
}
tasks.named("dependencyLicenses").configure {
mapping from: /jackson-.*/, to: 'jackson'
}
// not published, so no need for javadoc
tasks.named("javadoc").configure { enabled = false }
tasks.named("thirdPartyAudit").configure {
ignoreMissingClasses(
// from com.fasterxml.jackson.dataformat.yaml.YAMLMapper (jackson-dataformat-yaml)
'com.fasterxml.jackson.databind.ObjectMapper',
'com.fasterxml.jackson.databind.cfg.MapperBuilder'
)
}

View File

@ -0,0 +1 @@
a78a8747147d2c5807683e76ec2b633e95c14fe9

View File

@ -0,0 +1,176 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

View File

@ -0,0 +1,24 @@
***The art of simplicity is a puzzle of complexity.***
## Overview ##
[YAML](http://yaml.org) is a data serialization format designed for human readability and interaction with scripting languages.
SnakeYAML is a YAML processor for the Java Virtual Machine.
## SnakeYAML features ##
* a **complete** [YAML 1.1 processor](http://yaml.org/spec/1.1/current.html). In particular, SnakeYAML can parse all examples from the specification.
* Unicode support including UTF-8/UTF-16 input/output.
* high-level API for serializing and deserializing native Java objects.
* support for all types from the [YAML types repository](http://yaml.org/type/index.html).
* relatively sensible error messages.
## Info ##
* [Changes](https://bitbucket.org/asomov/snakeyaml/wiki/Changes)
* [Documentation](https://bitbucket.org/asomov/snakeyaml/wiki/Documentation)
## Contribute ##
* Mercurial DVCS is used to dance with the [source code](https://bitbucket.org/asomov/snakeyaml/src).
* If you find a bug in SnakeYAML, please [file a bug report](https://bitbucket.org/asomov/snakeyaml/issues?status=new&status=open).
* You may discuss SnakeYAML at
[the mailing list](http://groups.google.com/group/snakeyaml-core).

View File

@ -0,0 +1,144 @@
/*
* 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.provider;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.filter.FilteringParserDelegate;
import org.elasticsearch.core.RestApiVersion;
import org.elasticsearch.xcontent.DeprecationHandler;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.provider.filtering.FilterPathBasedFilter;
import org.elasticsearch.xcontent.support.filtering.FilterPath;
import java.util.Set;
public class XContentParserConfigurationImpl implements XContentParserConfiguration {
public static final XContentParserConfigurationImpl EMPTY = new XContentParserConfigurationImpl(
NamedXContentRegistry.EMPTY,
DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
RestApiVersion.current(),
null,
null,
false
);
final NamedXContentRegistry registry;
final DeprecationHandler deprecationHandler;
final RestApiVersion restApiVersion;
final FilterPath[] includes;
final FilterPath[] excludes;
final boolean filtersMatchFieldNamesWithDots;
private XContentParserConfigurationImpl(
NamedXContentRegistry registry,
DeprecationHandler deprecationHandler,
RestApiVersion restApiVersion,
FilterPath[] includes,
FilterPath[] excludes,
boolean filtersMatchFieldNamesWithDots
) {
this.registry = registry;
this.deprecationHandler = deprecationHandler;
this.restApiVersion = restApiVersion;
this.includes = includes;
this.excludes = excludes;
this.filtersMatchFieldNamesWithDots = filtersMatchFieldNamesWithDots;
}
@Override
public XContentParserConfigurationImpl withRegistry(NamedXContentRegistry registry) {
return new XContentParserConfigurationImpl(
registry,
deprecationHandler,
restApiVersion,
includes,
excludes,
filtersMatchFieldNamesWithDots
);
}
public NamedXContentRegistry registry() {
return registry;
}
public XContentParserConfiguration withDeprecationHandler(DeprecationHandler deprecationHandler) {
return new XContentParserConfigurationImpl(
registry,
deprecationHandler,
restApiVersion,
includes,
excludes,
filtersMatchFieldNamesWithDots
);
}
public DeprecationHandler deprecationHandler() {
return deprecationHandler;
}
public XContentParserConfiguration withRestApiVersion(RestApiVersion restApiVersion) {
return new XContentParserConfigurationImpl(
registry,
deprecationHandler,
restApiVersion,
includes,
excludes,
filtersMatchFieldNamesWithDots
);
}
public RestApiVersion restApiVersion() {
return restApiVersion;
}
public XContentParserConfiguration withFiltering(
Set<String> includeStrings,
Set<String> excludeStrings,
boolean filtersMatchFieldNamesWithDots
) {
return new XContentParserConfigurationImpl(
registry,
deprecationHandler,
restApiVersion,
FilterPath.compile(includeStrings),
FilterPath.compile(excludeStrings),
filtersMatchFieldNamesWithDots
);
}
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, filtersMatchFieldNamesWithDots),
true,
true
);
}
if (includes != null) {
filtered = new FilteringParserDelegate(
filtered,
new FilterPathBasedFilter(includes, true, filtersMatchFieldNamesWithDots),
true,
true
);
}
return filtered;
}
}

View File

@ -0,0 +1,97 @@
/*
* 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.provider;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.json.JsonStringEncoder;
import org.elasticsearch.xcontent.provider.cbor.CborXContentImpl;
import org.elasticsearch.xcontent.provider.json.JsonStringEncoderImpl;
import org.elasticsearch.xcontent.provider.json.JsonXContentImpl;
import org.elasticsearch.xcontent.provider.smile.SmileXContentImpl;
import org.elasticsearch.xcontent.provider.yaml.YamlXContentImpl;
import org.elasticsearch.xcontent.spi.XContentProvider;
import java.io.IOException;
public class XContentProviderImpl implements XContentProvider {
public XContentProviderImpl() {}
@Override
public FormatProvider getCborXContent() {
return new FormatProvider() {
@Override
public XContentBuilder getContentBuilder() throws IOException {
return CborXContentImpl.getContentBuilder();
}
@Override
public XContent XContent() {
return CborXContentImpl.cborXContent();
}
};
}
@Override
public FormatProvider getJsonXContent() {
return new FormatProvider() {
@Override
public XContentBuilder getContentBuilder() throws IOException {
return JsonXContentImpl.getContentBuilder();
}
@Override
public XContent XContent() {
return JsonXContentImpl.jsonXContent();
}
};
}
@Override
public FormatProvider getSmileXContent() {
return new FormatProvider() {
@Override
public XContentBuilder getContentBuilder() throws IOException {
return SmileXContentImpl.getContentBuilder();
}
@Override
public XContent XContent() {
return SmileXContentImpl.smileXContent();
}
};
}
@Override
public FormatProvider getYamlXContent() {
return new FormatProvider() {
@Override
public XContentBuilder getContentBuilder() throws IOException {
return YamlXContentImpl.getContentBuilder();
}
@Override
public XContent XContent() {
return YamlXContentImpl.yamlXContent();
}
};
}
@Override
public XContentParserConfiguration empty() {
return XContentParserConfigurationImpl.EMPTY;
}
@Override
public JsonStringEncoder getJsonStringEncoder() {
return JsonStringEncoderImpl.getInstance();
}
}

View File

@ -6,12 +6,12 @@
* Side Public License, v 1.
*/
package org.elasticsearch.xcontent.cbor;
package org.elasticsearch.xcontent.provider.cbor;
import com.fasterxml.jackson.core.JsonGenerator;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContentGenerator;
import org.elasticsearch.xcontent.provider.json.JsonXContentGenerator;
import java.io.OutputStream;
import java.util.Set;

View File

@ -0,0 +1,117 @@
/*
* 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.provider.cbor;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.dataformat.cbor.CBORConstants;
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParseException;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Set;
/**
* A CBOR based content implementation using Jackson.
*/
public final class CborXContentImpl implements XContent {
public static XContentBuilder getContentBuilder() throws IOException {
return XContentBuilder.builder(cborXContent);
}
static final CBORFactory cborFactory;
private static final CborXContentImpl cborXContent;
public static XContent cborXContent() {
return cborXContent;
}
static {
cborFactory = new CBORFactory();
cborFactory.configure(CBORFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW, false); // this trips on many mappings now...
// Do not automatically close unclosed objects/arrays in com.fasterxml.jackson.dataformat.cbor.CBORGenerator#close() method
cborFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, false);
cborFactory.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true);
cborXContent = new CborXContentImpl();
}
private CborXContentImpl() {}
@Override
public XContentType type() {
return XContentType.CBOR;
}
@Override
public byte streamSeparator() {
throw new XContentParseException("cbor does not support stream parsing...");
}
@Override
public boolean detectContent(byte[] bytes, int offset, int length) {
// CBOR logic similar to CBORFactory#hasCBORFormat
if (bytes[offset] == CBORConstants.BYTE_OBJECT_INDEFINITE && length > 1) {
return true;
}
if (CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_TAG, bytes[offset]) && length > 2) {
// Actually, specific "self-describe tag" is a very good indicator
if (bytes[offset] == (byte) 0xD9 && bytes[offset + 1] == (byte) 0xD9 && bytes[offset + 2] == (byte) 0xF7) {
return true;
}
}
// for small objects, some encoders just encode as major type object, we can safely
// say its CBOR since it doesn't contradict SMILE or JSON, and its a last resort
if (CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_OBJECT, bytes[offset])) {
return true;
}
return false;
}
@Override
public boolean detectContent(CharSequence chars) {
return false;
}
@Override
public XContentGenerator createGenerator(OutputStream os, Set<String> includes, Set<String> excludes) throws IOException {
return new CborXContentGenerator(cborFactory.createGenerator(os, JsonEncoding.UTF8), os, includes, excludes);
}
@Override
public XContentParser createParser(XContentParserConfiguration config, String content) throws IOException {
return new CborXContentParser(config, cborFactory.createParser(content));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, InputStream is) throws IOException {
return new CborXContentParser(config, cborFactory.createParser(is));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, byte[] data, int offset, int length) throws IOException {
return new CborXContentParser(config, cborFactory.createParser(data, offset, length));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, Reader reader) throws IOException {
return new CborXContentParser(config, cborFactory.createParser(reader));
}
}

View File

@ -6,13 +6,13 @@
* Side Public License, v 1.
*/
package org.elasticsearch.xcontent.cbor;
package org.elasticsearch.xcontent.provider.cbor;
import com.fasterxml.jackson.core.JsonParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContentParser;
import org.elasticsearch.xcontent.provider.json.JsonXContentParser;
public class CborXContentParser extends JsonXContentParser {

View File

@ -6,10 +6,12 @@
* Side Public License, v 1.
*/
package org.elasticsearch.xcontent.support.filtering;
package org.elasticsearch.xcontent.provider.filtering;
import com.fasterxml.jackson.core.filter.TokenFilter;
import org.elasticsearch.xcontent.support.filtering.FilterPath;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

View File

@ -0,0 +1,50 @@
/*
* 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.provider.json;
import org.elasticsearch.xcontent.json.JsonStringEncoder;
/**
* Encoder of JSON String values (including JSON field names) into Strings or UTF-8 byte arrays.
*
* @implNote The implementation simply delegates to the Jackson encoder.
*/
public final class JsonStringEncoderImpl extends JsonStringEncoder {
private static final JsonStringEncoderImpl INSTANCE = new JsonStringEncoderImpl();
private final com.fasterxml.jackson.core.io.JsonStringEncoder delegate;
public static JsonStringEncoderImpl getInstance() {
return INSTANCE;
}
private JsonStringEncoderImpl() {
delegate = com.fasterxml.jackson.core.io.JsonStringEncoder.getInstance();
}
@Override
public byte[] quoteAsUTF8(String text) {
return delegate.quoteAsUTF8(text);
}
@Override
public char[] quoteAsString(CharSequence input) {
return delegate.quoteAsString(input);
}
@Override
public char[] quoteAsString(String input) {
return delegate.quoteAsString(input);
}
public void quoteAsString(CharSequence input, StringBuilder output) {
delegate.quoteAsString(input, output);
}
}

View File

@ -6,8 +6,9 @@
* Side Public License, v 1.
*/
package org.elasticsearch.xcontent.json;
package org.elasticsearch.xcontent.provider.json;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonStreamContext;
import com.fasterxml.jackson.core.base.GeneratorBase;
@ -24,10 +25,11 @@ import org.elasticsearch.xcontent.DeprecationHandler;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentFactory;
import org.elasticsearch.xcontent.XContentGenerationException;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.support.filtering.FilterPathBasedFilter;
import org.elasticsearch.xcontent.provider.filtering.FilterPathBasedFilter;
import java.io.BufferedInputStream;
import java.io.IOException;
@ -149,156 +151,272 @@ public class JsonXContentGenerator implements XContentGenerator {
@Override
public void writeEndObject() throws IOException {
if (inRoot()) {
// Use the low level generator to write the startObject so that the root
// start object is always written even if a filtered generator is used
getLowLevelGenerator().writeEndObject();
return;
try {
if (inRoot()) {
// Use the low level generator to write the startObject so that the root
// start object is always written even if a filtered generator is used
getLowLevelGenerator().writeEndObject();
return;
}
generator.writeEndObject();
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
generator.writeEndObject();
}
@Override
public void writeStartArray() throws IOException {
generator.writeStartArray();
try {
generator.writeStartArray();
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeEndArray() throws IOException {
generator.writeEndArray();
try {
generator.writeEndArray();
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeFieldName(String name) throws IOException {
generator.writeFieldName(name);
try {
generator.writeFieldName(name);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNull() throws IOException {
generator.writeNull();
try {
generator.writeNull();
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNullField(String name) throws IOException {
generator.writeNullField(name);
try {
generator.writeNullField(name);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeBooleanField(String name, boolean value) throws IOException {
generator.writeBooleanField(name, value);
try {
generator.writeBooleanField(name, value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeBoolean(boolean value) throws IOException {
generator.writeBoolean(value);
try {
generator.writeBoolean(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumberField(String name, double value) throws IOException {
generator.writeNumberField(name, value);
try {
generator.writeNumberField(name, value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumber(double value) throws IOException {
generator.writeNumber(value);
try {
generator.writeNumber(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumberField(String name, float value) throws IOException {
generator.writeNumberField(name, value);
try {
generator.writeNumberField(name, value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumber(float value) throws IOException {
generator.writeNumber(value);
try {
generator.writeNumber(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumberField(String name, int value) throws IOException {
generator.writeNumberField(name, value);
try {
generator.writeNumberField(name, value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumberField(String name, BigInteger value) throws IOException {
// as jackson's JsonGenerator doesn't have this method for BigInteger
// we have to implement it ourselves
generator.writeFieldName(name);
generator.writeNumber(value);
try {
generator.writeFieldName(name);
generator.writeNumber(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumberField(String name, BigDecimal value) throws IOException {
generator.writeNumberField(name, value);
try {
generator.writeNumberField(name, value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumber(int value) throws IOException {
generator.writeNumber(value);
try {
generator.writeNumber(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumberField(String name, long value) throws IOException {
generator.writeNumberField(name, value);
try {
generator.writeNumberField(name, value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumber(long value) throws IOException {
generator.writeNumber(value);
try {
generator.writeNumber(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumber(short value) throws IOException {
generator.writeNumber(value);
try {
generator.writeNumber(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumber(BigInteger value) throws IOException {
generator.writeNumber(value);
try {
generator.writeNumber(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeNumber(BigDecimal value) throws IOException {
generator.writeNumber(value);
try {
generator.writeNumber(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeStringField(String name, String value) throws IOException {
generator.writeStringField(name, value);
try {
generator.writeStringField(name, value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeString(String value) throws IOException {
generator.writeString(value);
try {
generator.writeString(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeString(char[] value, int offset, int len) throws IOException {
generator.writeString(value, offset, len);
try {
generator.writeString(value, offset, len);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeUTF8String(byte[] value, int offset, int length) throws IOException {
generator.writeUTF8String(value, offset, length);
try {
generator.writeUTF8String(value, offset, length);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeBinaryField(String name, byte[] value) throws IOException {
generator.writeBinaryField(name, value);
try {
generator.writeBinaryField(name, value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeBinary(byte[] value) throws IOException {
generator.writeBinary(value);
try {
generator.writeBinary(value);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
@Override
public void writeBinary(byte[] value, int offset, int len) throws IOException {
generator.writeBinary(value, offset, len);
try {
generator.writeBinary(value, offset, len);
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
private void writeStartRaw(String name) throws IOException {
writeFieldName(name);
generator.writeRaw(':');
try {
writeFieldName(name);
generator.writeRaw(':');
} catch (JsonGenerationException e) {
throw new XContentGenerationException(e);
}
}
public void writeEndRaw() {

View File

@ -0,0 +1,103 @@
/*
* 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.provider.json;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Set;
/**
* A JSON based content implementation using Jackson.
*/
public class JsonXContentImpl implements XContent {
public static XContentBuilder getContentBuilder() throws IOException {
return XContentBuilder.builder(jsonXContent);
}
private static final JsonFactory jsonFactory;
public static final XContent jsonXContent;
public static final XContent jsonXContent() {
return jsonXContent;
}
static {
jsonFactory = new JsonFactory();
jsonFactory.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true);
jsonFactory.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
jsonFactory.configure(JsonFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW, false); // this trips on many mappings now...
// Do not automatically close unclosed objects/arrays in com.fasterxml.jackson.core.json.UTF8JsonGenerator#close() method
jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, false);
jsonFactory.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true);
jsonXContent = new JsonXContentImpl();
}
private JsonXContentImpl() {}
@Override
public XContentType type() {
return XContentType.JSON;
}
@Override
public byte streamSeparator() {
return '\n';
}
@Override
public boolean detectContent(byte[] bytes, int offset, int length) {
return bytes[offset] == '{';
}
@Override
public boolean detectContent(CharSequence chars) {
return chars.charAt(0) == '{';
}
@Override
public XContentGenerator createGenerator(OutputStream os, Set<String> includes, Set<String> excludes) throws IOException {
return new JsonXContentGenerator(jsonFactory.createGenerator(os, JsonEncoding.UTF8), os, includes, excludes);
}
@Override
public XContentParser createParser(XContentParserConfiguration config, String content) throws IOException {
return new JsonXContentParser(config, jsonFactory.createParser(content));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, InputStream is) throws IOException {
return new JsonXContentParser(config, jsonFactory.createParser(is));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, byte[] data, int offset, int length) throws IOException {
return new JsonXContentParser(config, jsonFactory.createParser(data, offset, length));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, Reader reader) throws IOException {
return new JsonXContentParser(config, jsonFactory.createParser(reader));
}
}

View File

@ -6,16 +6,23 @@
* Side Public License, v 1.
*/
package org.elasticsearch.xcontent.json;
package org.elasticsearch.xcontent.provider.json;
import com.fasterxml.jackson.core.JsonLocation;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.exc.InputCoercionException;
import com.fasterxml.jackson.core.io.JsonEOFException;
import org.elasticsearch.core.internal.io.IOUtils;
import org.elasticsearch.xcontent.XContentEOFException;
import org.elasticsearch.xcontent.XContentLocation;
import org.elasticsearch.xcontent.XContentParseException;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.provider.XContentParserConfigurationImpl;
import org.elasticsearch.xcontent.support.AbstractXContentParser;
import java.io.IOException;
@ -27,7 +34,7 @@ public class JsonXContentParser extends AbstractXContentParser {
public JsonXContentParser(XContentParserConfiguration config, JsonParser parser) {
super(config.registry(), config.deprecationHandler(), config.restApiVersion());
this.parser = config.filter(parser);
this.parser = ((XContentParserConfigurationImpl) config).filter(parser);
}
@Override
@ -40,9 +47,20 @@ public class JsonXContentParser extends AbstractXContentParser {
parser.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, allowDuplicateKeys == false);
}
private static XContentParseException newXContentParseException(JsonProcessingException e) {
JsonLocation loc = e.getLocation();
throw new XContentParseException(new XContentLocation(loc.getLineNr(), loc.getColumnNr()), e.getMessage(), e);
}
@Override
public Token nextToken() throws IOException {
return convertToken(parser.nextToken());
try {
return convertToken(parser.nextToken());
} catch (JsonEOFException e) {
throw new XContentEOFException(e);
} catch (JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
@ -67,7 +85,11 @@ public class JsonXContentParser extends AbstractXContentParser {
@Override
protected boolean doBooleanValue() throws IOException {
return parser.getBooleanValue();
try {
return parser.getBooleanValue();
} catch (JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
@ -80,7 +102,11 @@ public class JsonXContentParser extends AbstractXContentParser {
@Override
public CharBuffer charBuffer() throws IOException {
return CharBuffer.wrap(parser.getTextCharacters(), parser.getTextOffset(), parser.getTextLength());
try {
return CharBuffer.wrap(parser.getTextCharacters(), parser.getTextOffset(), parser.getTextLength());
} catch (JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
@ -126,52 +152,92 @@ public class JsonXContentParser extends AbstractXContentParser {
@Override
public char[] textCharacters() throws IOException {
return parser.getTextCharacters();
try {
return parser.getTextCharacters();
} catch (JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
public int textLength() throws IOException {
return parser.getTextLength();
try {
return parser.getTextLength();
} catch (JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
public int textOffset() throws IOException {
return parser.getTextOffset();
try {
return parser.getTextOffset();
} catch (JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
public Number numberValue() throws IOException {
return parser.getNumberValue();
try {
return parser.getNumberValue();
} catch (InputCoercionException | JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
public short doShortValue() throws IOException {
return parser.getShortValue();
try {
return parser.getShortValue();
} catch (InputCoercionException | JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
public int doIntValue() throws IOException {
return parser.getIntValue();
try {
return parser.getIntValue();
} catch (InputCoercionException | JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
public long doLongValue() throws IOException {
return parser.getLongValue();
try {
return parser.getLongValue();
} catch (InputCoercionException | JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
public float doFloatValue() throws IOException {
return parser.getFloatValue();
try {
return parser.getFloatValue();
} catch (InputCoercionException | JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
public double doDoubleValue() throws IOException {
return parser.getDoubleValue();
try {
return parser.getDoubleValue();
} catch (InputCoercionException | JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override
public byte[] binaryValue() throws IOException {
return parser.getBinaryValue();
try {
return parser.getBinaryValue();
} catch (JsonParseException e) {
throw newXContentParseException(e);
}
}
@Override

View File

@ -6,12 +6,12 @@
* Side Public License, v 1.
*/
package org.elasticsearch.xcontent.smile;
package org.elasticsearch.xcontent.provider.smile;
import com.fasterxml.jackson.core.JsonGenerator;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContentGenerator;
import org.elasticsearch.xcontent.provider.json.JsonXContentGenerator;
import java.io.OutputStream;
import java.util.Set;

View File

@ -0,0 +1,110 @@
/*
* 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.provider.smile;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.dataformat.smile.SmileConstants;
import com.fasterxml.jackson.dataformat.smile.SmileFactory;
import com.fasterxml.jackson.dataformat.smile.SmileGenerator;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Set;
/**
* A Smile based content implementation using Jackson.
*/
public final class SmileXContentImpl implements XContent {
public static XContentBuilder getContentBuilder() throws IOException {
return XContentBuilder.builder(smileXContent);
}
static final SmileFactory smileFactory;
private static final SmileXContentImpl smileXContent;
public static XContent smileXContent() {
return smileXContent;
}
static {
smileFactory = new SmileFactory();
// for now, this is an overhead, might make sense for web sockets
smileFactory.configure(SmileGenerator.Feature.ENCODE_BINARY_AS_7BIT, false);
smileFactory.configure(SmileFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW, false); // this trips on many mappings now...
// Do not automatically close unclosed objects/arrays in com.fasterxml.jackson.dataformat.smile.SmileGenerator#close() method
smileFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, false);
smileFactory.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true);
smileXContent = new SmileXContentImpl();
}
private SmileXContentImpl() {}
@Override
public XContentType type() {
return XContentType.SMILE;
}
@Override
public byte streamSeparator() {
return (byte) 0xFF;
}
@Override
public boolean detectContent(byte[] bytes, int offset, int length) {
return length > 2
&& bytes[offset] == SmileConstants.HEADER_BYTE_1
&& bytes[offset + 1] == SmileConstants.HEADER_BYTE_2
&& bytes[offset + 2] == SmileConstants.HEADER_BYTE_3;
}
@Override
public boolean detectContent(CharSequence chars) {
return chars.length() > 2
&& chars.charAt(0) == SmileConstants.HEADER_BYTE_1
&& chars.charAt(1) == SmileConstants.HEADER_BYTE_2
&& chars.charAt(2) == SmileConstants.HEADER_BYTE_3;
}
@Override
public XContentGenerator createGenerator(OutputStream os, Set<String> includes, Set<String> excludes) throws IOException {
return new SmileXContentGenerator(smileFactory.createGenerator(os, JsonEncoding.UTF8), os, includes, excludes);
}
@Override
public XContentParser createParser(XContentParserConfiguration config, String content) throws IOException {
return new SmileXContentParser(config, smileFactory.createParser(content));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, InputStream is) throws IOException {
return new SmileXContentParser(config, smileFactory.createParser(is));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, byte[] data, int offset, int length) throws IOException {
return new SmileXContentParser(config, smileFactory.createParser(data, offset, length));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, Reader reader) throws IOException {
return new SmileXContentParser(config, smileFactory.createParser(reader));
}
}

View File

@ -6,13 +6,13 @@
* Side Public License, v 1.
*/
package org.elasticsearch.xcontent.smile;
package org.elasticsearch.xcontent.provider.smile;
import com.fasterxml.jackson.core.JsonParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContentParser;
import org.elasticsearch.xcontent.provider.json.JsonXContentParser;
public class SmileXContentParser extends JsonXContentParser {

View File

@ -6,12 +6,12 @@
* Side Public License, v 1.
*/
package org.elasticsearch.xcontent.yaml;
package org.elasticsearch.xcontent.provider.yaml;
import com.fasterxml.jackson.core.JsonGenerator;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContentGenerator;
import org.elasticsearch.xcontent.provider.json.JsonXContentGenerator;
import java.io.OutputStream;
import java.util.Set;

View File

@ -0,0 +1,96 @@
/*
* 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.provider.yaml;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Set;
/**
* A YAML based content implementation using Jackson.
*/
public final class YamlXContentImpl implements XContent {
public static XContentBuilder getContentBuilder() throws IOException {
return XContentBuilder.builder(yamlXContent);
}
static final YAMLFactory yamlFactory;
private static final YamlXContentImpl yamlXContent;
public static XContent yamlXContent() {
return yamlXContent;
}
static {
yamlFactory = new YAMLFactory();
yamlFactory.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true);
yamlXContent = new YamlXContentImpl();
}
private YamlXContentImpl() {}
@Override
public XContentType type() {
return XContentType.YAML;
}
@Override
public byte streamSeparator() {
throw new UnsupportedOperationException("yaml does not support stream parsing...");
}
@Override
public boolean detectContent(byte[] bytes, int offset, int length) {
return length > 2 && bytes[offset] == '-' && bytes[offset + 1] == '-' && bytes[offset + 2] == '-';
}
@Override
public boolean detectContent(CharSequence chars) {
return chars.length() > 2 && chars.charAt(0) == '-' && chars.charAt(1) == '-' && chars.charAt(2) == '-';
}
@Override
public XContentGenerator createGenerator(OutputStream os, Set<String> includes, Set<String> excludes) throws IOException {
return new YamlXContentGenerator(yamlFactory.createGenerator(os, JsonEncoding.UTF8), os, includes, excludes);
}
@Override
public XContentParser createParser(XContentParserConfiguration config, String content) throws IOException {
return new YamlXContentParser(config, yamlFactory.createParser(content));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, InputStream is) throws IOException {
return new YamlXContentParser(config, yamlFactory.createParser(is));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, byte[] data, int offset, int length) throws IOException {
return new YamlXContentParser(config, yamlFactory.createParser(data, offset, length));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, Reader reader) throws IOException {
return new YamlXContentParser(config, yamlFactory.createParser(reader));
}
}

View File

@ -6,13 +6,13 @@
* Side Public License, v 1.
*/
package org.elasticsearch.xcontent.yaml;
package org.elasticsearch.xcontent.provider.yaml;
import com.fasterxml.jackson.core.JsonParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContentParser;
import org.elasticsearch.xcontent.provider.json.JsonXContentParser;
public class YamlXContentParser extends JsonXContentParser {

View File

@ -0,0 +1 @@
org.elasticsearch.xcontent.provider.XContentProviderImpl

View File

@ -0,0 +1,40 @@
/*
* 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.internal;
import com.fasterxml.jackson.dataformat.cbor.CBORConstants;
import com.fasterxml.jackson.dataformat.smile.SmileConstants;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xcontent.XContentFactory;
import org.elasticsearch.xcontent.XContentType;
import static org.hamcrest.Matchers.equalTo;
public class CborTests extends ESTestCase {
public void testCBORBasedOnMajorObjectDetection() {
// for this {"f "=> 5} perl encoder for example generates:
byte[] bytes = new byte[] { (byte) 0xA1, (byte) 0x43, (byte) 0x66, (byte) 6f, (byte) 6f, (byte) 0x5 };
assertThat(XContentFactory.xContentType(bytes), equalTo(XContentType.CBOR));
// this if for {"foo" : 5} in python CBOR
bytes = new byte[] { (byte) 0xA1, (byte) 0x63, (byte) 0x66, (byte) 0x6f, (byte) 0x6f, (byte) 0x5 };
assertThat(XContentFactory.xContentType(bytes), equalTo(XContentType.CBOR));
assertThat(((Number) XContentHelper.convertToMap(new BytesArray(bytes), true).v2().get("foo")).intValue(), equalTo(5));
// also make sure major type check doesn't collide with SMILE and JSON, just in case
assertThat(CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_OBJECT, SmileConstants.HEADER_BYTE_1), equalTo(false));
assertThat(CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_OBJECT, (byte) '{'), equalTo(false));
assertThat(CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_OBJECT, (byte) ' '), equalTo(false));
assertThat(CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_OBJECT, (byte) '-'), equalTo(false));
}
}

View File

@ -14,6 +14,7 @@ import com.fasterxml.jackson.core.filter.FilteringGeneratorDelegate;
import org.elasticsearch.common.io.stream.BytesStreamOutput;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xcontent.provider.filtering.FilterPathBasedFilter;
import java.util.Arrays;
import java.util.stream.Collectors;

View File

@ -0,0 +1,18 @@
/*
* 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 java.io.IOException;
public class XContentEOFException extends IOException {
public XContentEOFException(IOException cause) {
super(cause);
}
}

View File

@ -149,7 +149,6 @@ public class XContentFactory {
if (YamlXContent.yamlXContent.detectContent(content)) {
return XContentType.YAML;
}
// CBOR is not supported
// fallback for JSON
@ -288,7 +287,7 @@ public class XContentFactory {
if (SmileXContent.smileXContent.detectContent(bytes, offset, length)) {
return XContentType.SMILE;
}
if (length > 2 && first == '-' && bytes[offset + 1] == '-' && bytes[offset + 2] == '-') {
if (YamlXContent.yamlXContent.detectContent(bytes, offset, length)) {
return XContentType.YAML;
}
if (CborXContent.cborXContent.detectContent(bytes, offset, length)) {

View File

@ -0,0 +1,19 @@
/*
* 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 java.io.IOException;
public class XContentGenerationException extends IOException {
public XContentGenerationException(IOException cause) {
super(cause);
}
}

View File

@ -8,155 +8,52 @@
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 org.elasticsearch.xcontent.spi.XContentProvider;
import java.util.Set;
/**
* Configuration for {@link XContentParser}.
*/
public class XContentParserConfiguration {
public interface 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,
false
);
final NamedXContentRegistry registry;
final DeprecationHandler deprecationHandler;
final RestApiVersion restApiVersion;
final FilterPath[] includes;
final FilterPath[] excludes;
final boolean filtersMatchFieldNamesWithDots;
private XContentParserConfiguration(
NamedXContentRegistry registry,
DeprecationHandler deprecationHandler,
RestApiVersion restApiVersion,
FilterPath[] includes,
FilterPath[] excludes,
boolean filtersMatchFieldNamesWithDots
) {
this.registry = registry;
this.deprecationHandler = deprecationHandler;
this.restApiVersion = restApiVersion;
this.includes = includes;
this.excludes = excludes;
this.filtersMatchFieldNamesWithDots = filtersMatchFieldNamesWithDots;
}
XContentParserConfiguration EMPTY = XContentProvider.provider().empty();
/**
* Replace the registry backing {@link XContentParser#namedObject}.
*/
public XContentParserConfiguration withRegistry(NamedXContentRegistry registry) {
return new XContentParserConfiguration(
registry,
deprecationHandler,
restApiVersion,
includes,
excludes,
filtersMatchFieldNamesWithDots
);
}
XContentParserConfiguration withRegistry(NamedXContentRegistry registry);
public NamedXContentRegistry registry() {
return registry;
}
NamedXContentRegistry 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,
filtersMatchFieldNamesWithDots
);
}
XContentParserConfiguration withDeprecationHandler(DeprecationHandler deprecationHandler);
public DeprecationHandler deprecationHandler() {
return deprecationHandler;
}
DeprecationHandler deprecationHandler();
/**
* Replace the {@link XContentParser#getRestApiVersion() claimed}
* {@link RestApiVersion}.
*/
public XContentParserConfiguration withRestApiVersion(RestApiVersion restApiVersion) {
return new XContentParserConfiguration(
registry,
deprecationHandler,
restApiVersion,
includes,
excludes,
filtersMatchFieldNamesWithDots
);
}
XContentParserConfiguration withRestApiVersion(RestApiVersion restApiVersion);
public RestApiVersion restApiVersion() {
return restApiVersion;
}
RestApiVersion restApiVersion();
/**
* Replace the configured filtering.
*/
public XContentParserConfiguration withFiltering(
XContentParserConfiguration withFiltering(
Set<String> includeStrings,
Set<String> excludeStrings,
boolean filtersMatchFieldNamesWithDots
) {
return new XContentParserConfiguration(
registry,
deprecationHandler,
restApiVersion,
FilterPath.compile(includeStrings),
FilterPath.compile(excludeStrings),
filtersMatchFieldNamesWithDots
);
}
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, filtersMatchFieldNamesWithDots),
true,
true
);
}
if (includes != null) {
filtered = new FilteringParserDelegate(
filtered,
new FilterPathBasedFilter(includes, true, filtersMatchFieldNamesWithDots),
true,
true
);
}
return filtered;
}
);
}

View File

@ -8,106 +8,25 @@
package org.elasticsearch.xcontent.cbor;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.dataformat.cbor.CBORConstants;
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParseException;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.spi.XContentProvider;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Set;
/**
* A CBOR based content implementation using Jackson.
* CBOR based content.
*/
public class CborXContent implements XContent {
public final class CborXContent {
public static XContentBuilder contentBuilder() throws IOException {
return XContentBuilder.builder(cborXContent);
}
static final CBORFactory cborFactory;
public static final CborXContent cborXContent;
static {
cborFactory = new CBORFactory();
cborFactory.configure(CBORFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW, false); // this trips on many mappings now...
// Do not automatically close unclosed objects/arrays in com.fasterxml.jackson.dataformat.cbor.CBORGenerator#close() method
cborFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, false);
cborFactory.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true);
cborXContent = new CborXContent();
}
private static final XContentProvider.FormatProvider provider = XContentProvider.provider().getCborXContent();
private CborXContent() {}
@Override
public XContentType type() {
return XContentType.CBOR;
public static XContentBuilder contentBuilder() throws IOException {
return provider.getContentBuilder();
}
@Override
public byte streamSeparator() {
throw new XContentParseException("cbor does not support stream parsing...");
}
public static final XContent cborXContent = provider.XContent();
@Override
public boolean detectContent(byte[] bytes, int offset, int length) {
// CBOR logic similar to CBORFactory#hasCBORFormat
if (bytes[offset] == CBORConstants.BYTE_OBJECT_INDEFINITE && length > 1) {
return true;
}
if (CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_TAG, bytes[offset]) && length > 2) {
// Actually, specific "self-describe tag" is a very good indicator
if (bytes[offset] == (byte) 0xD9 && bytes[offset + 1] == (byte) 0xD9 && bytes[offset + 2] == (byte) 0xF7) {
return true;
}
}
// for small objects, some encoders just encode as major type object, we can safely
// say its CBOR since it doesn't contradict SMILE or JSON, and its a last resort
if (CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_OBJECT, bytes[offset])) {
return true;
}
return false;
}
@Override
public boolean detectContent(CharSequence chars) {
return false;
}
@Override
public XContentGenerator createGenerator(OutputStream os, Set<String> includes, Set<String> excludes) throws IOException {
return new CborXContentGenerator(cborFactory.createGenerator(os, JsonEncoding.UTF8), os, includes, excludes);
}
@Override
public XContentParser createParser(XContentParserConfiguration config, String content) throws IOException {
return new CborXContentParser(config, cborFactory.createParser(content));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, InputStream is) throws IOException {
return new CborXContentParser(config, cborFactory.createParser(is));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, byte[] data, int offset, int length) throws IOException {
return new CborXContentParser(config, cborFactory.createParser(data, offset, length));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, Reader reader) throws IOException {
return new CborXContentParser(config, cborFactory.createParser(reader));
}
}

View File

@ -0,0 +1,187 @@
/*
* 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.internal;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UncheckedIOException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.CodeSigner;
import java.security.CodeSource;
import java.security.PrivilegedAction;
import java.security.SecureClassLoader;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Objects;
/**
* A class loader that is responsible for loading implementation classes and resources embedded within an archive.
*
* <p> This loader facilitates a scenario whereby an API can embed its implementation and dependencies all within the same archive as the
* API itself. The archive can be put directly on the class path, where it's API classes are loadable by the application class loader, but
* the embedded implementation and dependencies are not. When locating a concrete provider, the API can create an instance of an
* EmbeddedImplClassLoader to locate and load the implementation.
*
* <p> The archive typically consists of two disjoint logically groups:
* 1. the top-level classes and resources,
* 2. the embedded classes and resources
*
* <p> The top-level classes and resources are typically loaded and located, respectively, by the parent of an EmbeddedImplClassLoader
* loader. The embedded classes and resources, are located by the parent loader as pure resources with a provider specific name prefix, and
* classes are defined by the EmbeddedImplClassLoader. The list of prefixes is determined by reading the entries in the MANIFEST.TXT.
*
* <p> For example, the structure of the archive named x-content:
* <pre>
* /org/elasticsearch/xcontent/XContent.class
* /IMPL-JARS/x-content/LISTING.TXT - contains list of jar file names, newline separated
* /IMPL-JARS/x-content/x-content-impl.jar/xxx
* /IMPL-JARS/x-content/dep-1.jar/abc
* /IMPL-JARS/x-content/dep-2.jar/xyz
* </pre>
*/
public final class EmbeddedImplClassLoader extends SecureClassLoader {
private static final String IMPL_PREFIX = "IMPL-JARS/";
private static final String MANIFEST_FILE = "/LISTING.TXT";
private final List<String> prefixes;
private final ClassLoader parent;
private final Map<String, CodeSource> prefixToCodeBase;
private static Map<String, CodeSource> getProviderPrefixes(ClassLoader parent, String providerName) {
String providerPrefix = IMPL_PREFIX + providerName;
URL manifest = parent.getResource(providerPrefix + MANIFEST_FILE);
if (manifest == null) {
throw new IllegalStateException("missing x-content provider jars list");
}
try (
InputStream in = manifest.openStream();
InputStreamReader isr = new InputStreamReader(in, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(isr)
) {
List<String> jars = reader.lines().toList();
Map<String, CodeSource> map = new HashMap<>();
for (String jar : jars) {
map.put(providerPrefix + "/" + jar, new CodeSource(new URL(manifest, jar), (CodeSigner[]) null /*signers*/));
}
return Collections.unmodifiableMap(map);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
static EmbeddedImplClassLoader getInstance(ClassLoader parent, String providerName) {
return new EmbeddedImplClassLoader(parent, getProviderPrefixes(parent, providerName));
}
private EmbeddedImplClassLoader(ClassLoader parent, Map<String, CodeSource> prefixToCodeBase) {
super(parent);
this.prefixes = prefixToCodeBase.keySet().stream().toList();
this.prefixToCodeBase = prefixToCodeBase;
this.parent = parent;
}
record Resource(InputStream inputStream, CodeSource codeSource) {}
/** Searches for the named resource. Iterates over all prefixes. */
private Resource privilegedGetResourceOrNull(String name) {
return AccessController.doPrivileged(new PrivilegedAction<Resource>() {
@Override
public Resource run() {
for (String prefix : prefixes) {
URL url = parent.getResource(prefix + "/" + name);
if (url != null) {
try {
InputStream is = url.openStream();
return new Resource(is, prefixToCodeBase.get(prefix));
} catch (IOException e) {
// silently ignore, same as ClassLoader
}
}
}
return null;
}
});
}
@Override
public Class<?> findClass(String name) throws ClassNotFoundException {
String filepath = name.replace('.', '/').concat(".class");
Resource res = privilegedGetResourceOrNull(filepath);
if (res != null) {
try (InputStream in = res.inputStream()) {
byte[] bytes = in.readAllBytes();
return defineClass(name, bytes, 0, bytes.length, res.codeSource());
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
return super.findClass(name);
}
@Override
protected URL findResource(String name) {
Objects.requireNonNull(name);
URL url = prefixes.stream().map(p -> p + "/" + name).map(parent::getResource).filter(Objects::nonNull).findFirst().orElse(null);
if (url != null) {
return url;
}
return super.findResource(name);
}
@Override
protected Enumeration<URL> findResources(String name) throws IOException {
final int size = prefixes.size();
@SuppressWarnings("unchecked")
Enumeration<URL>[] tmp = (Enumeration<URL>[]) new Enumeration<?>[size + 1];
for (int i = 0; i < size; i++) {
tmp[i] = parent.getResources(prefixes.get(i) + "/" + name);
}
tmp[size] = super.findResources(name);
return new CompoundEnumeration<>(tmp);
}
static final class CompoundEnumeration<E> implements Enumeration<E> {
private final Enumeration<E>[] enumerations;
private int index;
CompoundEnumeration(Enumeration<E>[] enumerations) {
this.enumerations = enumerations;
}
private boolean next() {
while (index < enumerations.length) {
if (enumerations[index] != null && enumerations[index].hasMoreElements()) {
return true;
}
index++;
}
return false;
}
public boolean hasMoreElements() {
return next();
}
public E nextElement() {
if (next() == false) {
throw new NoSuchElementException();
}
return enumerations[index].nextElement();
}
}
}

View File

@ -0,0 +1,44 @@
/*
* 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.internal;
import org.elasticsearch.xcontent.spi.XContentProvider;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ServiceLoader;
/**
* A provider locator for finding the {@link XContentProvider}.
*/
public final class ProviderLocator {
/**
* Returns the provider instance.
*/
public static final XContentProvider INSTANCE = provider();
private static XContentProvider provider() {
try {
PrivilegedExceptionAction<XContentProvider> pa = ProviderLocator::loadAsNonModule;
return AccessController.doPrivileged(pa);
} catch (PrivilegedActionException e) {
throw new UncheckedIOException((IOException) e.getCause());
}
}
private static XContentProvider loadAsNonModule() {
ClassLoader loader = EmbeddedImplClassLoader.getInstance(ProviderLocator.class.getClassLoader(), "x-content");
ServiceLoader<XContentProvider> sl = ServiceLoader.load(XContentProvider.class, loader);
return sl.findFirst().orElseThrow(() -> new RuntimeException("cannot locate x-content provider"));
}
}

View File

@ -0,0 +1,48 @@
/*
* 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.json;
import org.elasticsearch.xcontent.spi.XContentProvider;
/**
* Encoder of JSON String values (including JSON field names) into Strings or UTF-8 byte arrays.
*/
public abstract class JsonStringEncoder {
private static final JsonStringEncoder INSTANCE = XContentProvider.provider().getJsonStringEncoder();
/**
* Factory method for getting an instance.
*/
public static JsonStringEncoder getInstance() {
return INSTANCE;
}
/**
* Quotes a given JSON String value using standard quoting, encoding as UTF-8, and return results as a byte array.
*/
public abstract byte[] quoteAsUTF8(String text);
/**
* Quotes text contents using JSON standard quoting, and return results as a character array.
*/
public abstract char[] quoteAsString(CharSequence input);
/**
* Quotes text contents using JSON standard quoting, and return results as a character array.
*/
public abstract char[] quoteAsString(String input);
/**
* Quotes text contents using JSON standard quoting, appending the results to the given {@link StringBuilder}.
* Use this variant if you have e.g. a {@link StringBuilder} and want to avoid superfluous copying of it.
*/
public abstract void quoteAsString(CharSequence input, StringBuilder output);
}

View File

@ -8,92 +8,30 @@
package org.elasticsearch.xcontent.json;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.spi.XContentProvider;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Set;
/**
* A JSON based content implementation using Jackson.
* JSON based XContent.
*/
public class JsonXContent implements XContent {
public final class JsonXContent {
public static XContentBuilder contentBuilder() throws IOException {
return XContentBuilder.builder(jsonXContent);
}
private static final JsonFactory jsonFactory;
public static final JsonXContent jsonXContent;
static {
jsonFactory = new JsonFactory();
jsonFactory.configure(JsonGenerator.Feature.QUOTE_FIELD_NAMES, true);
jsonFactory.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
jsonFactory.configure(JsonFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW, false); // this trips on many mappings now...
// Do not automatically close unclosed objects/arrays in com.fasterxml.jackson.core.json.UTF8JsonGenerator#close() method
jsonFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, false);
jsonFactory.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true);
jsonXContent = new JsonXContent();
}
private static final XContentProvider.FormatProvider provider = XContentProvider.provider().getJsonXContent();
private JsonXContent() {}
@Override
public XContentType type() {
return XContentType.JSON;
/**
* Returns a {@link XContentBuilder} for building JSON XContent.
*/
public static XContentBuilder contentBuilder() throws IOException {
return provider.getContentBuilder();
}
@Override
public byte streamSeparator() {
return '\n';
}
@Override
public boolean detectContent(byte[] bytes, int offset, int length) {
return bytes[offset] == '{';
}
@Override
public boolean detectContent(CharSequence chars) {
return chars.charAt(0) == '{';
}
@Override
public XContentGenerator createGenerator(OutputStream os, Set<String> includes, Set<String> excludes) throws IOException {
return new JsonXContentGenerator(jsonFactory.createGenerator(os, JsonEncoding.UTF8), os, includes, excludes);
}
@Override
public XContentParser createParser(XContentParserConfiguration config, String content) throws IOException {
return new JsonXContentParser(config, jsonFactory.createParser(content));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, InputStream is) throws IOException {
return new JsonXContentParser(config, jsonFactory.createParser(is));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, byte[] data, int offset, int length) throws IOException {
return new JsonXContentParser(config, jsonFactory.createParser(data, offset, length));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, Reader reader) throws IOException {
return new JsonXContentParser(config, jsonFactory.createParser(reader));
}
/**
* A JSON based XContent.
*/
public static final XContent jsonXContent = provider.XContent();
}

View File

@ -8,99 +8,31 @@
package org.elasticsearch.xcontent.smile;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.dataformat.smile.SmileConstants;
import com.fasterxml.jackson.dataformat.smile.SmileFactory;
import com.fasterxml.jackson.dataformat.smile.SmileGenerator;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.spi.XContentProvider;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Set;
/**
* A Smile based content implementation using Jackson.
* Smile based XContent.
*/
public class SmileXContent implements XContent {
public final class SmileXContent {
public static XContentBuilder contentBuilder() throws IOException {
return XContentBuilder.builder(smileXContent);
}
static final SmileFactory smileFactory;
public static final SmileXContent smileXContent;
static {
smileFactory = new SmileFactory();
// for now, this is an overhead, might make sense for web sockets
smileFactory.configure(SmileGenerator.Feature.ENCODE_BINARY_AS_7BIT, false);
smileFactory.configure(SmileFactory.Feature.FAIL_ON_SYMBOL_HASH_OVERFLOW, false); // this trips on many mappings now...
// Do not automatically close unclosed objects/arrays in com.fasterxml.jackson.dataformat.smile.SmileGenerator#close() method
smileFactory.configure(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT, false);
smileFactory.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true);
smileXContent = new SmileXContent();
}
private static final XContentProvider.FormatProvider provider = XContentProvider.provider().getSmileXContent();
private SmileXContent() {}
@Override
public XContentType type() {
return XContentType.SMILE;
/**
* Returns an {@link XContentBuilder} for building Smile XContent.
*/
public static XContentBuilder contentBuilder() throws IOException {
return provider.getContentBuilder();
}
@Override
public byte streamSeparator() {
return (byte) 0xFF;
}
/**
* A Smile based XContent.
*/
public static final XContent smileXContent = provider.XContent();
@Override
public boolean detectContent(byte[] bytes, int offset, int length) {
return length > 2
&& bytes[offset] == SmileConstants.HEADER_BYTE_1
&& bytes[offset + 1] == SmileConstants.HEADER_BYTE_2
&& bytes[offset + 2] == SmileConstants.HEADER_BYTE_3;
}
@Override
public boolean detectContent(CharSequence chars) {
return chars.length() > 2
&& chars.charAt(0) == SmileConstants.HEADER_BYTE_1
&& chars.charAt(1) == SmileConstants.HEADER_BYTE_2
&& chars.charAt(2) == SmileConstants.HEADER_BYTE_3;
}
@Override
public XContentGenerator createGenerator(OutputStream os, Set<String> includes, Set<String> excludes) throws IOException {
return new SmileXContentGenerator(smileFactory.createGenerator(os, JsonEncoding.UTF8), os, includes, excludes);
}
@Override
public XContentParser createParser(XContentParserConfiguration config, String content) throws IOException {
return new SmileXContentParser(config, smileFactory.createParser(content));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, InputStream is) throws IOException {
return new SmileXContentParser(config, smileFactory.createParser(is));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, byte[] data, int offset, int length) throws IOException {
return new SmileXContentParser(config, smileFactory.createParser(data, offset, length));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, Reader reader) throws IOException {
return new SmileXContentParser(config, smileFactory.createParser(reader));
}
}

View File

@ -0,0 +1,77 @@
/*
* 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.spi;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.internal.ProviderLocator;
import org.elasticsearch.xcontent.json.JsonStringEncoder;
import java.io.IOException;
/**
* A provider for the XContent API.
*
* A provider supports all the XContent formats, JSON, CBOR, SMILE, and YAML.
*/
public interface XContentProvider {
/**
* A provider of a specific content format, e.g. JSON
*/
interface FormatProvider {
/**
* Returns a {@link XContentBuilder} for building the format specific content.
*/
XContentBuilder getContentBuilder() throws IOException;
/**
* Returns an instance of the format specific content.
*/
XContent XContent();
}
/**
* Returns the CBOR format provider.
*/
FormatProvider getCborXContent();
/**
* Returns the JSON format provider.
*/
FormatProvider getJsonXContent();
/**
* Returns the SMILE format provider.
*/
FormatProvider getSmileXContent();
/**
* Returns the YAML format provider.
*/
FormatProvider getYamlXContent();
/**
* Returns an empty XContentParserConfiguration.
*/
XContentParserConfiguration empty();
/**
* Returns a JsonStringEncoder.
*/
JsonStringEncoder getJsonStringEncoder();
/**
* Returns the located provider instance.
*/
static XContentProvider provider() {
return ProviderLocator.INSTANCE;
}
}

View File

@ -71,7 +71,7 @@ public class FilterPath {
* @param matchFieldNamesWithDots support dot in field name or not
* @return true if the name equal a final node, otherwise return false
*/
boolean matches(String name, List<FilterPath> nextFilters, boolean matchFieldNamesWithDots) {
public boolean matches(String name, List<FilterPath> nextFilters, boolean matchFieldNamesWithDots) { // << here
if (nextFilters == null) {
return false;
}

View File

@ -8,85 +8,28 @@
package org.elasticsearch.xcontent.yaml;
import com.fasterxml.jackson.core.JsonEncoding;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.spi.XContentProvider;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.Reader;
import java.util.Set;
/**
* A YAML based content implementation using Jackson.
* YAML based content.
*/
public class YamlXContent implements XContent {
public final class YamlXContent {
public static XContentBuilder contentBuilder() throws IOException {
return XContentBuilder.builder(yamlXContent);
}
static final YAMLFactory yamlFactory;
public static final YamlXContent yamlXContent;
static {
yamlFactory = new YAMLFactory();
yamlFactory.configure(JsonParser.Feature.STRICT_DUPLICATE_DETECTION, true);
yamlXContent = new YamlXContent();
}
private static final XContentProvider.FormatProvider provider = XContentProvider.provider().getYamlXContent();
private YamlXContent() {}
@Override
public XContentType type() {
return XContentType.YAML;
/**
* Returns an {@link XContentBuilder} for building YAML based content.
*/
public static XContentBuilder contentBuilder() throws IOException {
return provider.getContentBuilder();
}
@Override
public byte streamSeparator() {
throw new UnsupportedOperationException("yaml does not support stream parsing...");
}
public static final XContent yamlXContent = provider.XContent();
@Override
public boolean detectContent(byte[] bytes, int offset, int length) {
return length > 2 && bytes[offset] == '-' && bytes[offset + 1] == '-' && bytes[offset + 2] == '-';
}
@Override
public boolean detectContent(CharSequence chars) {
return chars.length() > 2 && chars.charAt(0) == '-' && chars.charAt(1) == '-' && chars.charAt(2) == '-';
}
@Override
public XContentGenerator createGenerator(OutputStream os, Set<String> includes, Set<String> excludes) throws IOException {
return new YamlXContentGenerator(yamlFactory.createGenerator(os, JsonEncoding.UTF8), os, includes, excludes);
}
@Override
public XContentParser createParser(XContentParserConfiguration config, String content) throws IOException {
return new YamlXContentParser(config, yamlFactory.createParser(content));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, InputStream is) throws IOException {
return new YamlXContentParser(config, yamlFactory.createParser(is));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, byte[] data, int offset, int length) throws IOException {
return new YamlXContentParser(config, yamlFactory.createParser(data, offset, length));
}
@Override
public XContentParser createParser(XContentParserConfiguration config, Reader reader) throws IOException {
return new YamlXContentParser(config, yamlFactory.createParser(reader));
}
}

View File

@ -8,8 +8,6 @@
package org.elasticsearch.xcontent;
import com.fasterxml.jackson.core.JsonParseException;
import org.elasticsearch.common.CheckedSupplier;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
@ -216,7 +214,7 @@ public class XContentParserTests extends ESTestCase {
if (token.equals(XContentParser.Token.VALUE_STRING)) {
expectThrows(IllegalArgumentException.class, parser::booleanValue);
} else {
expectThrows(JsonParseException.class, parser::booleanValue);
expectThrows(XContentParseException.class, parser::booleanValue);
}
token = parser.nextToken();
@ -228,7 +226,7 @@ public class XContentParserTests extends ESTestCase {
if (token.equals(XContentParser.Token.VALUE_STRING)) {
expectThrows(IllegalArgumentException.class, parser::booleanValue);
} else {
expectThrows(JsonParseException.class, parser::booleanValue);
expectThrows(XContentParseException.class, parser::booleanValue);
}
}
}

View File

@ -22,6 +22,7 @@ dependencies {
// geoip2 dependencies:
api("com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}")
api("com.fasterxml.jackson.core:jackson-databind:${versions.jackson}")
api("com.fasterxml.jackson.core:jackson-core:${versions.jackson}")
api('com.maxmind.db:maxmind-db:1.3.1')
testImplementation 'org.elasticsearch:geolite2-databases:20191119'
@ -95,6 +96,7 @@ tasks.named("forbiddenPatterns").configure {
tasks.named("dependencyLicenses").configure {
mapping from: /geoip.*/, to: 'maxmind-geolite2-eula'
mapping from: /maxmind-db.*/, to: 'maxmind-db-reader'
mapping from: /jackson.*/, to: 'jackson'
ignoreFile 'elastic-geoip-database-service-agreement-LICENSE.txt'
}
@ -111,4 +113,5 @@ testClusters.configureEach {
tasks.named("yamlRestTestV7CompatTransform").configure { task ->
task.skipTestsByFilePattern("**/ingest_geoip/20_geoip_processor.yml", "from 8.0 yaml rest tests use geoip test fixture and default geoip are no longer packaged. In 7.x yaml tests used default databases which makes tests results very different, so skipping these tests")
// task.skipTest("lang_mustache/50_multi_search_template/Multi-search template with errors", "xxx")
}

View File

@ -0,0 +1 @@
8796585e716440d6dd5128b30359932a9eb74d0d

View File

@ -28,4 +28,5 @@ restResources {
tasks.named("yamlRestTestV7CompatTransform").configure {task ->
task.addAllowedWarningRegex("\\[types removal\\].*")
task.replaceValueInMatch("responses.1.error.root_cause.0.type", "x_content_e_o_f_exception", "Multi-search template with errors")
}

View File

@ -8,7 +8,6 @@
package org.elasticsearch.script.mustache;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import com.github.mustachejava.Code;
import com.github.mustachejava.DefaultMustacheFactory;
import com.github.mustachejava.DefaultMustacheVisitor;
@ -23,6 +22,7 @@ import com.github.mustachejava.codes.WriteCode;
import org.elasticsearch.common.Strings;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonStringEncoder;
import java.io.IOException;
import java.io.StringWriter;

View File

@ -101,7 +101,7 @@ setup:
trackTotalHits: 1
- match: { responses.0.hits.total: 2 }
- match: { responses.1.error.root_cause.0.type: json_e_o_f_exception }
- match: { responses.1.error.root_cause.0.type: x_content_e_o_f_exception }
- match: { responses.1.error.root_cause.0.reason: "/Unexpected.end.of.input/" }
- match: { responses.2.hits.total: 1 }
- match: { responses.3.error.root_cause.0.type: parsing_exception }

View File

@ -19,6 +19,7 @@ dependencies {
api "org.apache.lucene:lucene-spatial-extras:${versions.lucene}"
api "org.locationtech.spatial4j:spatial4j:${versions.spatial4j}"
api "org.locationtech.jts:jts-core:${versions.jts}"
implementation "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
testImplementation project(":test:framework")
}
@ -56,5 +57,6 @@ tasks.named("thirdPartyAudit").configure {
tasks.named("dependencyLicenses").configure {
mapping from: /lucene-.*/, to: 'lucene'
mapping from: /jackson-.*/, to: 'jackson'
}

View File

@ -0,0 +1 @@
8796585e716440d6dd5128b30359932a9eb74d0d

View File

@ -0,0 +1 @@
8796585e716440d6dd5128b30359932a9eb74d0d

View File

@ -50,6 +50,7 @@ dependencies {
api 'com.google.http-client:google-http-client-gson:1.39.2'
api 'com.google.http-client:google-http-client-appengine:1.39.2'
api 'com.google.http-client:google-http-client-jackson2:1.39.2'
api "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
api 'com.google.api:gax-httpjson:0.83.0'
api 'io.grpc:grpc-context:1.39.0'
api 'io.opencensus:opencensus-api:0.28.0'
@ -81,6 +82,7 @@ tasks.named("dependencyLicenses").configure {
mapping from: /opencensus.*/, to: 'opencensus'
mapping from: /protobuf.*/, to: 'protobuf'
mapping from: /proto-google.*/, to: 'proto-google'
mapping from: /jackson.*/, to: 'jackson'
}
tasks.named("thirdPartyAudit").configure {

View File

@ -0,0 +1,8 @@
This copy of Jackson JSON processor streaming parser/generator is licensed under the
Apache (Software) License, version 2.0 ("the License").
See the License for details about distribution rights, and the
specific rights regarding derivate works.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0

View File

@ -0,0 +1,20 @@
# Jackson JSON processor
Jackson is a high-performance, Free/Open Source JSON processing library.
It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
been in development since 2007.
It is currently developed by a community of developers, as well as supported
commercially by FasterXML.com.
## Licensing
Jackson core and extension components may licensed under different licenses.
To find the details that apply to this artifact see the accompanying LICENSE file.
For more information, including possible other licensing options, contact
FasterXML.com (http://fasterxml.com).
## Credits
A list of contributors may be found from CREDITS file, which is included
in some artifacts (usually source distributions); but is always available
from the source code management (SCM) system project uses.

View File

@ -0,0 +1 @@
8796585e716440d6dd5128b30359932a9eb74d0d

View File

@ -0,0 +1 @@
8796585e716440d6dd5128b30359932a9eb74d0d

View File

@ -0,0 +1 @@
c854bb2d46138198cb5d4aae86ef6c04b8bc1e70

View File

@ -27,8 +27,10 @@ dependencies {
api "commons-logging:commons-logging:${versions.commonslogging}"
api "org.apache.logging.log4j:log4j-1.2-api:${versions.log4j}"
api "commons-codec:commons-codec:${versions.commonscodec}"
api "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
api "com.fasterxml.jackson.core:jackson-databind:${versions.jackson}"
api "com.fasterxml.jackson.core:jackson-annotations:${versions.jackson}"
api "com.fasterxml.jackson.dataformat:jackson-dataformat-cbor:${versions.jackson}"
api "joda-time:joda-time:2.10.10"
}

View File

@ -0,0 +1 @@
8796585e716440d6dd5128b30359932a9eb74d0d

View File

@ -0,0 +1 @@
c854bb2d46138198cb5d4aae86ef6c04b8bc1e70

View File

@ -16,6 +16,7 @@ dependencies {
api "com.google.oauth-client:google-oauth-client:${versions.google}"
api "com.google.http-client:google-http-client:${versions.google}"
api "com.google.http-client:google-http-client-jackson2:${versions.google}"
api "com.fasterxml.jackson.core:jackson-core:${versions.jackson}"
api 'com.google.code.findbugs:jsr305:1.3.9'
api "commons-logging:commons-logging:${versions.commonslogging}"
api "org.apache.logging.log4j:log4j-1.2-api:${versions.log4j}"
@ -30,6 +31,7 @@ restResources {
tasks.named("dependencyLicenses").configure {
mapping from: /google-.*/, to: 'google'
mapping from: /jackson-.*/, to: 'jackson'
}
tasks.named("check").configure {

View File

@ -0,0 +1,8 @@
This copy of Jackson JSON processor streaming parser/generator is licensed under the
Apache (Software) License, version 2.0 ("the License").
See the License for details about distribution rights, and the
specific rights regarding derivate works.
You may obtain a copy of the License at:
http://www.apache.org/licenses/LICENSE-2.0

View File

@ -0,0 +1,20 @@
# Jackson JSON processor
Jackson is a high-performance, Free/Open Source JSON processing library.
It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
been in development since 2007.
It is currently developed by a community of developers, as well as supported
commercially by FasterXML.com.
## Licensing
Jackson core and extension components may licensed under different licenses.
To find the details that apply to this artifact see the accompanying LICENSE file.
For more information, including possible other licensing options, contact
FasterXML.com (http://fasterxml.com).
## Credits
A list of contributors may be found from CREDITS file, which is included
in some artifacts (usually source distributions); but is always available
from the source code management (SCM) system project uses.

View File

@ -0,0 +1 @@
8796585e716440d6dd5128b30359932a9eb74d0d

View File

@ -143,6 +143,13 @@ tasks.named("thirdPartyAudit").configure {
// from log4j
'com.conversantmedia.util.concurrent.SpinPolicy',
'com.fasterxml.jackson.core.JsonGenerator',
'com.fasterxml.jackson.core.JsonParser',
'com.fasterxml.jackson.core.JsonParser$Feature',
'com.fasterxml.jackson.core.JsonToken',
'com.fasterxml.jackson.core.PrettyPrinter',
'com.fasterxml.jackson.core.type.TypeReference',
'com.fasterxml.jackson.dataformat.yaml.YAMLMapper',
'com.fasterxml.jackson.databind.SerializationFeature',
'com.fasterxml.jackson.annotation.JsonInclude$Include',
'com.fasterxml.jackson.databind.DeserializationContext',

View File

@ -8,8 +8,6 @@
package org.elasticsearch;
import com.fasterxml.jackson.core.JsonParseException;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.lucene.index.CorruptIndexException;
@ -20,6 +18,7 @@ import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
import org.elasticsearch.core.Nullable;
import org.elasticsearch.index.Index;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.xcontent.XContentParseException;
import java.io.IOException;
import java.io.PrintWriter;
@ -62,7 +61,7 @@ public final class ExceptionsHelper {
return ((ElasticsearchException) t).status();
} else if (t instanceof IllegalArgumentException) {
return RestStatus.BAD_REQUEST;
} else if (t instanceof JsonParseException) {
} else if (t instanceof XContentParseException) {
return RestStatus.BAD_REQUEST;
} else if (t instanceof EsRejectedExecutionException) {
return RestStatus.TOO_MANY_REQUESTS;

View File

@ -8,8 +8,6 @@
package org.elasticsearch.action.bulk;
import com.fasterxml.jackson.core.io.JsonEOFException;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.index.IndexRequest;
@ -26,6 +24,7 @@ import org.elasticsearch.rest.action.document.RestBulkAction;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.xcontent.ParseField;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentEOFException;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParserConfiguration;
import org.elasticsearch.xcontent.XContentType;
@ -424,7 +423,7 @@ public final class BulkRequestParser {
XContentParser.Token token;
try {
token = parser.nextToken();
} catch (JsonEOFException ignore) {
} catch (XContentEOFException ignore) {
deprecationLogger.compatibleCritical(
STRICT_ACTION_PARSING_WARNING_KEY,
"A bulk action wasn't closed properly with the closing brace. Malformed objects are currently accepted but will be "

View File

@ -17,8 +17,6 @@
*/
package org.elasticsearch.common.logging;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import org.apache.logging.log4j.core.LogEvent;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.plugins.Plugin;
@ -27,6 +25,7 @@ import org.apache.logging.log4j.core.pattern.ExtendedThrowablePatternConverter;
import org.apache.logging.log4j.core.pattern.PatternConverter;
import org.apache.logging.log4j.core.pattern.ThrowablePatternConverter;
import org.apache.logging.log4j.util.Strings;
import org.elasticsearch.xcontent.json.JsonStringEncoder;
import java.nio.charset.Charset;
import java.util.StringJoiner;

View File

@ -8,8 +8,6 @@
package org.elasticsearch.index;
import com.fasterxml.jackson.core.io.JsonStringEncoder;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -22,6 +20,7 @@ import org.elasticsearch.index.shard.SearchOperationListener;
import org.elasticsearch.search.internal.SearchContext;
import org.elasticsearch.tasks.Task;
import org.elasticsearch.xcontent.ToXContent;
import org.elasticsearch.xcontent.json.JsonStringEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Collections;

View File

@ -8,9 +8,6 @@
package org.elasticsearch.index.mapper;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.exc.InputCoercionException;
import org.apache.lucene.document.DoublePoint;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FloatPoint;
@ -1451,7 +1448,7 @@ public class NumberFieldMapper extends FieldMapper {
Number value;
try {
value = value(context.parser(), type, nullValue, coerce());
} catch (InputCoercionException | IllegalArgumentException | JsonParseException e) {
} catch (IllegalArgumentException e) {
if (ignoreMalformed.value() && context.parser().currentToken().isValue()) {
context.addIgnoredField(mappedFieldType.name());
return;
@ -1466,13 +1463,11 @@ public class NumberFieldMapper extends FieldMapper {
/**
* Read the value at the current position of the parser.
* @throws InputCoercionException if xcontent couldn't convert the value in the required type, for example, integer overflow
* @throws JsonParseException if there was any error parsing the json
* @throws IllegalArgumentException if there was an error parsing the value from the json
* @throws IOException if there was any other IO error
*/
private static Number value(XContentParser parser, NumberType numberType, Number nullValue, boolean coerce)
throws InputCoercionException, JsonParseException, IllegalArgumentException, IOException {
throws IllegalArgumentException, IOException {
if (parser.currentToken() == Token.VALUE_NULL) {
return nullValue;

View File

@ -14,6 +14,7 @@ import org.elasticsearch.common.Strings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestStatusToXContentListener;
import org.elasticsearch.xcontent.XContentParseException;
import java.io.IOException;
import java.util.List;
@ -43,7 +44,7 @@ public class RestClearScrollAction extends BaseRestHandler {
// NOTE: if rest request with xcontent body has request parameters, values parsed from request body have the precedence
try {
clearRequest.fromXContent(xContentParser);
} catch (IOException e) {
} catch (IOException | XContentParseException e) {
throw new IllegalArgumentException("Failed to parse request body", e);
}
}

View File

@ -14,6 +14,7 @@ import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestStatusToXContentListener;
import org.elasticsearch.search.Scroll;
import org.elasticsearch.xcontent.XContentParseException;
import java.io.IOException;
import java.util.Collections;
@ -57,7 +58,7 @@ public class RestSearchScrollAction extends BaseRestHandler {
// NOTE: if rest request with xcontent body has request parameters, values parsed from request body have the precedence
try {
searchScrollRequest.fromXContent(xContentParser);
} catch (IOException e) {
} catch (IOException | XContentParseException e) {
throw new IllegalArgumentException("Failed to parse request body", e);
}
}

View File

@ -48,6 +48,10 @@ grant codeBase "${codebase.elasticsearch-plugin-classloader}" {
permission java.lang.RuntimePermission "createClassLoader";
};
grant codeBase "${codebase.elasticsearch-x-content}" {
permission java.lang.RuntimePermission "createClassLoader";
};
grant codeBase "${codebase.jna}" {
// for registering native methods
permission java.lang.RuntimePermission "accessDeclaredMembers";

View File

@ -8,8 +8,6 @@
package org.elasticsearch;
import com.fasterxml.jackson.core.JsonParseException;
import org.apache.commons.codec.DecoderException;
import org.apache.lucene.index.CorruptIndexException;
import org.elasticsearch.action.ShardOperationFailedException;
@ -24,6 +22,7 @@ import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchShardTarget;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.transport.RemoteClusterAware;
import org.elasticsearch.xcontent.XContentParseException;
import java.io.IOException;
import java.util.Optional;
@ -85,7 +84,7 @@ public class ExceptionsHelperTests extends ESTestCase {
public void testStatus() {
assertThat(ExceptionsHelper.status(new IllegalArgumentException("illegal")), equalTo(RestStatus.BAD_REQUEST));
assertThat(ExceptionsHelper.status(new JsonParseException(null, "illegal")), equalTo(RestStatus.BAD_REQUEST));
assertThat(ExceptionsHelper.status(new XContentParseException(null, "illegal")), equalTo(RestStatus.BAD_REQUEST));
assertThat(ExceptionsHelper.status(new EsRejectedExecutionException("rejected")), equalTo(RestStatus.TOO_MANY_REQUESTS));
}

View File

@ -8,8 +8,6 @@
package org.elasticsearch.cluster.metadata;
import com.fasterxml.jackson.core.JsonParseException;
import org.elasticsearch.ResourceNotFoundException;
import org.elasticsearch.Version;
import org.elasticsearch.action.ActionListener;
@ -38,6 +36,7 @@ import org.elasticsearch.test.ClusterServiceUtils;
import org.elasticsearch.test.ESSingleNodeTestCase;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.xcontent.NamedXContentRegistry;
import org.elasticsearch.xcontent.XContentParseException;
import java.io.IOException;
import java.time.Instant;
@ -432,7 +431,7 @@ public class MetadataIndexTemplateServiceTests extends ESSingleNodeTestCase {
);
ComponentTemplate componentTemplate2 = new ComponentTemplate(template, 1L, new HashMap<>());
expectThrows(
JsonParseException.class,
XContentParseException.class,
() -> metadataIndexTemplateService.addComponentTemplate(throwState, true, "foo2", componentTemplate2)
);

View File

@ -8,10 +8,6 @@
package org.elasticsearch.common.xcontent;
import com.fasterxml.jackson.core.JsonGenerationException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParseException;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.Constants;
import org.elasticsearch.cluster.metadata.IndexMetadata;
@ -32,6 +28,7 @@ import org.elasticsearch.xcontent.ToXContentObject;
import org.elasticsearch.xcontent.XContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentFactory;
import org.elasticsearch.xcontent.XContentGenerationException;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParseException;
import org.elasticsearch.xcontent.XContentParser;
@ -82,7 +79,6 @@ import static org.hamcrest.Matchers.endsWith;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.instanceOf;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.startsWith;
public abstract class BaseXContentTestCase extends ESTestCase {
@ -912,7 +908,7 @@ public abstract class BaseXContentTestCase extends ESTestCase {
}
protected void doTestBigInteger(JsonGenerator generator, ByteArrayOutputStream os) throws Exception {
protected void doTestBigInteger(XContentGenerator generator, ByteArrayOutputStream os) throws Exception {
// Big integers cannot be handled explicitly, but if some values happen to be big ints,
// we can still call parser.map() and get the bigint value so that eg. source filtering
// keeps working
@ -1079,8 +1075,8 @@ public abstract class BaseXContentTestCase extends ESTestCase {
public void testChecksForDuplicates() throws Exception {
XContentBuilder builder = builder().startObject().field("key", 1).field("key", 2).endObject();
try (XContentParser xParser = createParser(builder)) {
JsonParseException pex = expectThrows(JsonParseException.class, () -> xParser.map());
assertThat(pex.getMessage(), startsWith("Duplicate field 'key'"));
XContentParseException pex = expectThrows(XContentParseException.class, () -> xParser.map());
assertThat(pex.getMessage(), containsString("Duplicate field 'key'"));
}
}
@ -1147,12 +1143,12 @@ public abstract class BaseXContentTestCase extends ESTestCase {
}
private static void expectValueException(ThrowingRunnable runnable) {
JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
XContentGenerationException e = expectThrows(XContentGenerationException.class, runnable);
assertThat(e.getMessage(), containsString("expecting a value"));
}
private static void expectFieldException(ThrowingRunnable runnable) {
JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
XContentGenerationException e = expectThrows(XContentGenerationException.class, runnable);
assertThat(e.getMessage(), containsString("expecting field name"));
}
@ -1162,12 +1158,12 @@ public abstract class BaseXContentTestCase extends ESTestCase {
}
private static void expectObjectException(ThrowingRunnable runnable) {
JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
XContentGenerationException e = expectThrows(XContentGenerationException.class, runnable);
assertThat(e.getMessage(), containsString("Current context not Object"));
}
private static void expectArrayException(ThrowingRunnable runnable) {
JsonGenerationException e = expectThrows(JsonGenerationException.class, runnable);
XContentGenerationException e = expectThrows(XContentGenerationException.class, runnable);
assertThat(e.getMessage(), containsString("Current context not Array"));
}

View File

@ -8,9 +8,6 @@
package org.elasticsearch.common.xcontent;
import com.fasterxml.jackson.dataformat.cbor.CBORConstants;
import com.fasterxml.jackson.dataformat.smile.SmileConstants;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesArray;
import org.elasticsearch.common.bytes.BytesReference;
@ -77,24 +74,6 @@ public class XContentFactoryTests extends ESTestCase {
}
}
public void testCBORBasedOnMajorObjectDetection() {
// for this {"f "=> 5} perl encoder for example generates:
byte[] bytes = new byte[] { (byte) 0xA1, (byte) 0x43, (byte) 0x66, (byte) 6f, (byte) 6f, (byte) 0x5 };
assertThat(XContentFactory.xContentType(bytes), equalTo(XContentType.CBOR));
// assertThat(((Number) XContentHelper.convertToMap(bytes, true).v2().get("foo")).intValue(), equalTo(5));
// this if for {"foo" : 5} in python CBOR
bytes = new byte[] { (byte) 0xA1, (byte) 0x63, (byte) 0x66, (byte) 0x6f, (byte) 0x6f, (byte) 0x5 };
assertThat(XContentFactory.xContentType(bytes), equalTo(XContentType.CBOR));
assertThat(((Number) XContentHelper.convertToMap(new BytesArray(bytes), true).v2().get("foo")).intValue(), equalTo(5));
// also make sure major type check doesn't collide with SMILE and JSON, just in case
assertThat(CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_OBJECT, SmileConstants.HEADER_BYTE_1), equalTo(false));
assertThat(CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_OBJECT, (byte) '{'), equalTo(false));
assertThat(CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_OBJECT, (byte) ' '), equalTo(false));
assertThat(CBORConstants.hasMajorType(CBORConstants.MAJOR_TYPE_OBJECT, (byte) '-'), equalTo(false));
}
public void testCBORBasedOnMagicHeaderDetection() {
byte[] bytes = new byte[] { (byte) 0xd9, (byte) 0xd9, (byte) 0xf7 };
assertThat(XContentFactory.xContentType(bytes), equalTo(XContentType.CBOR));

View File

@ -8,12 +8,11 @@
package org.elasticsearch.common.xcontent.cbor;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
import org.elasticsearch.common.xcontent.BaseXContentTestCase;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.cbor.CborXContent;
import java.io.ByteArrayOutputStream;
@ -26,7 +25,7 @@ public class CborXContentTests extends BaseXContentTestCase {
public void testBigInteger() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JsonGenerator generator = new CBORFactory().createGenerator(os);
XContentGenerator generator = CborXContent.cborXContent.createGenerator(os);
doTestBigInteger(generator, os);
}

View File

@ -8,11 +8,10 @@
package org.elasticsearch.common.xcontent.json;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonGenerator;
import org.elasticsearch.common.xcontent.BaseXContentTestCase;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContent;
import java.io.ByteArrayOutputStream;
@ -25,7 +24,7 @@ public class JsonXContentTests extends BaseXContentTestCase {
public void testBigInteger() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JsonGenerator generator = new JsonFactory().createGenerator(os);
XContentGenerator generator = JsonXContent.jsonXContent.createGenerator(os);
doTestBigInteger(generator, os);
}
}

View File

@ -8,12 +8,11 @@
package org.elasticsearch.common.xcontent.smile;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.dataformat.smile.SmileFactory;
import org.elasticsearch.common.xcontent.BaseXContentTestCase;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.smile.SmileXContent;
import java.io.ByteArrayOutputStream;
@ -26,7 +25,7 @@ public class SmileXContentTests extends BaseXContentTestCase {
public void testBigInteger() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JsonGenerator generator = new SmileFactory().createGenerator(os);
XContentGenerator generator = SmileXContent.smileXContent.createGenerator(os);
doTestBigInteger(generator, os);
}

View File

@ -8,11 +8,10 @@
package org.elasticsearch.common.xcontent.yaml;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import org.elasticsearch.common.xcontent.BaseXContentTestCase;
import org.elasticsearch.xcontent.XContentGenerator;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.yaml.YamlXContent;
import java.io.ByteArrayOutputStream;
@ -25,7 +24,7 @@ public class YamlXContentTests extends BaseXContentTestCase {
public void testBigInteger() throws Exception {
ByteArrayOutputStream os = new ByteArrayOutputStream();
JsonGenerator generator = new YAMLFactory().createGenerator(os);
XContentGenerator generator = YamlXContent.yamlXContent.createGenerator(os);
doTestBigInteger(generator, os);
}
}

View File

@ -8,8 +8,6 @@
package org.elasticsearch.index;
import com.fasterxml.jackson.core.JsonParseException;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@ -34,6 +32,7 @@ import org.elasticsearch.index.mapper.SeqNoFieldMapper;
import org.elasticsearch.index.mapper.Uid;
import org.elasticsearch.index.shard.ShardId;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xcontent.XContentParseException;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContent;
import org.junit.AfterClass;
@ -41,7 +40,6 @@ import org.junit.BeforeClass;
import org.mockito.Mockito;
import java.io.IOException;
import java.io.UncheckedIOException;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.emptyOrNullString;
@ -289,21 +287,12 @@ public class IndexingSlowLogTests extends ESTestCase {
null
);
final UncheckedIOException e = expectThrows(UncheckedIOException.class, () -> IndexingSlowLogMessage.of(index, doc, 10, true, 3));
final XContentParseException e = expectThrows(
XContentParseException.class,
() -> IndexingSlowLogMessage.of(index, doc, 10, true, 3)
);
assertThat(
e,
hasToString(
containsString(
"_failed_to_convert_[Unrecognized token 'invalid':"
+ " was expecting (JSON String, Number, Array, Object or token 'null', 'true' or 'false')\\n"
+ " at [Source: "
)
)
);
assertNotNull(e.getCause());
assertThat(e.getCause(), instanceOf(JsonParseException.class));
assertThat(
e.getCause(),
hasToString(
containsString(
"Unrecognized token 'invalid':"

View File

@ -8,8 +8,6 @@
package org.elasticsearch.index.mapper.flattened;
import com.fasterxml.jackson.core.JsonParseException;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.common.bytes.BytesReference;
@ -18,6 +16,7 @@ import org.elasticsearch.index.mapper.MockFieldMapper.FakeFieldType;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.XContentTestUtils;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentParseException;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContent;
@ -357,7 +356,7 @@ public class FlattenedFieldParserTests extends ESTestCase {
String input = "{ \"key\": [true, false }";
XContentParser xContentParser = createXContentParser(input);
expectThrows(JsonParseException.class, () -> parser.parse(xContentParser));
expectThrows(XContentParseException.class, () -> parser.parse(xContentParser));
}
public void testEmptyObject() throws Exception {

View File

@ -8,8 +8,6 @@
package org.elasticsearch.index.query.functionscore;
import com.fasterxml.jackson.core.JsonParseException;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.index.Term;
@ -50,6 +48,7 @@ import org.elasticsearch.script.ScriptType;
import org.elasticsearch.search.MultiValueMode;
import org.elasticsearch.test.AbstractQueryTestCase;
import org.elasticsearch.test.TestGeoShapeFieldMapperPlugin;
import org.elasticsearch.xcontent.XContentParseException;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;
import org.hamcrest.CoreMatchers;
@ -600,7 +599,7 @@ public class FunctionScoreQueryBuilderTests extends AbstractQueryTestCase<Functi
]
}
}""";
JsonParseException e = expectThrows(JsonParseException.class, () -> parseQuery(json));
XContentParseException e = expectThrows(XContentParseException.class, () -> parseQuery(json));
assertThat(e.getMessage(), containsString("Unexpected character ('{"));
}

View File

@ -16,11 +16,10 @@ import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.test.client.NoOpNodeClient;
import org.elasticsearch.test.rest.FakeRestRequest;
import org.elasticsearch.xcontent.XContentFactory;
import org.elasticsearch.xcontent.XContentParseException;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;
import java.io.IOException;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.Matchers.notNullValue;
@ -97,7 +96,7 @@ public class RestAnalyzeActionTests extends ESTestCase {
XContentType.JSON
).build();
try (NodeClient client = new NoOpNodeClient(this.getClass().getSimpleName())) {
IOException e = expectThrows(IOException.class, () -> action.handleRequest(request, null, client));
var e = expectThrows(XContentParseException.class, () -> action.handleRequest(request, null, client));
assertThat(e.getMessage(), containsString("expecting double-quote"));
}
}

View File

@ -8,8 +8,6 @@
package org.elasticsearch.search.builder;
import com.fasterxml.jackson.core.JsonParseException;
import org.elasticsearch.Version;
import org.elasticsearch.common.ParsingException;
import org.elasticsearch.common.bytes.BytesReference;
@ -33,6 +31,7 @@ import org.elasticsearch.test.VersionUtils;
import org.elasticsearch.xcontent.ToXContent;
import org.elasticsearch.xcontent.XContentBuilder;
import org.elasticsearch.xcontent.XContentFactory;
import org.elasticsearch.xcontent.XContentParseException;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentType;
import org.elasticsearch.xcontent.json.JsonXContent;
@ -61,7 +60,7 @@ public class SearchSourceBuilderTests extends AbstractSearchTestCase {
public void testFromXContentInvalid() throws IOException {
try (XContentParser parser = createParser(JsonXContent.jsonXContent, "{}}")) {
JsonParseException exc = expectThrows(JsonParseException.class, () -> SearchSourceBuilder.fromXContent(parser));
XContentParseException exc = expectThrows(XContentParseException.class, () -> SearchSourceBuilder.fromXContent(parser));
assertThat(exc.getMessage(), containsString("Unexpected close marker"));
}

View File

@ -109,6 +109,9 @@ include projects.toArray(new String[0])
project(":libs").children.each { libsProject ->
libsProject.name = "elasticsearch-${libsProject.name}"
libsProject.children.each { lp ->
lp.name = lp.name // for :libs:elasticsearch-x-content:impl
}
}
project(":test:external-modules").children.each { testProject ->

Some files were not shown because too many files have changed in this diff Show More