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:
parent
37beabcb2e
commit
070fcaa0ad
|
@ -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 {
|
||||
|
|
|
@ -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() + ".");
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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'
|
||||
)
|
||||
}
|
|
@ -0,0 +1 @@
|
|||
a78a8747147d2c5807683e76ec2b633e95c14fe9
|
|
@ -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
|
|
@ -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).
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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() {
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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
|
|
@ -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;
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
@ -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;
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
|
@ -0,0 +1 @@
|
|||
org.elasticsearch.xcontent.provider.XContentProviderImpl
|
|
@ -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));
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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"));
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
8796585e716440d6dd5128b30359932a9eb74d0d
|
|
@ -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")
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
8796585e716440d6dd5128b30359932a9eb74d0d
|
|
@ -0,0 +1 @@
|
|||
8796585e716440d6dd5128b30359932a9eb74d0d
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
|
@ -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.
|
|
@ -0,0 +1 @@
|
|||
8796585e716440d6dd5128b30359932a9eb74d0d
|
|
@ -0,0 +1 @@
|
|||
8796585e716440d6dd5128b30359932a9eb74d0d
|
|
@ -0,0 +1 @@
|
|||
c854bb2d46138198cb5d4aae86ef6c04b8bc1e70
|
|
@ -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"
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
8796585e716440d6dd5128b30359932a9eb74d0d
|
|
@ -0,0 +1 @@
|
|||
c854bb2d46138198cb5d4aae86ef6c04b8bc1e70
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
|
@ -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.
|
|
@ -0,0 +1 @@
|
|||
8796585e716440d6dd5128b30359932a9eb74d0d
|
|
@ -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',
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 "
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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':"
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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 ('{"));
|
||||
}
|
||||
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"));
|
||||
}
|
||||
|
||||
|
|
|
@ -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
Loading…
Reference in New Issue