Decouple XContentGenerator and JsonXContentGenerator from BytesReference (#28772)
This removes the link these two classes have with BytesReference, in favor of an `InputStream` approach. Relates to #28504
This commit is contained in:
parent
b29ba25c86
commit
5bb79558e7
|
@ -323,7 +323,7 @@ public class PutMappingRequest extends AcknowledgedRequest<PutMappingRequest> im
|
||||||
@Override
|
@Override
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
if (source != null) {
|
if (source != null) {
|
||||||
builder.rawValue(new BytesArray(source), XContentType.JSON);
|
builder.rawValue(new BytesArray(source).streamInput(), XContentType.JSON);
|
||||||
} else {
|
} else {
|
||||||
builder.startObject().endObject();
|
builder.startObject().endObject();
|
||||||
}
|
}
|
||||||
|
|
|
@ -987,7 +987,7 @@ public final class XContentBuilder implements Releasable, Flushable {
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public XContentBuilder rawField(String name, BytesReference value) throws IOException {
|
public XContentBuilder rawField(String name, BytesReference value) throws IOException {
|
||||||
generator.writeRawField(name, value);
|
generator.writeRawField(name, value.streamInput());
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -995,25 +995,15 @@ public final class XContentBuilder implements Releasable, Flushable {
|
||||||
* Writes a raw field with the given bytes as the value
|
* Writes a raw field with the given bytes as the value
|
||||||
*/
|
*/
|
||||||
public XContentBuilder rawField(String name, BytesReference value, XContentType contentType) throws IOException {
|
public XContentBuilder rawField(String name, BytesReference value, XContentType contentType) throws IOException {
|
||||||
generator.writeRawField(name, value, contentType);
|
generator.writeRawField(name, value.streamInput(), contentType);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a value with the source coming directly from the bytes
|
* Writes a value with the source coming directly from the bytes in the stream
|
||||||
* @deprecated use {@link #rawValue(BytesReference, XContentType)} to avoid content type auto-detection
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
public XContentBuilder rawValue(InputStream stream, XContentType contentType) throws IOException {
|
||||||
public XContentBuilder rawValue(BytesReference value) throws IOException {
|
generator.writeRawValue(stream, contentType);
|
||||||
generator.writeRawValue(value);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a value with the source coming directly from the bytes
|
|
||||||
*/
|
|
||||||
public XContentBuilder rawValue(BytesReference value, XContentType contentType) throws IOException {
|
|
||||||
generator.writeRawValue(value, contentType);
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
|
|
||||||
package org.elasticsearch.common.xcontent;
|
package org.elasticsearch.common.xcontent;
|
||||||
|
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.Flushable;
|
import java.io.Flushable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -99,28 +97,9 @@ public interface XContentGenerator extends Closeable, Flushable {
|
||||||
void writeRawField(String name, InputStream value, XContentType xContentType) throws IOException;
|
void writeRawField(String name, InputStream value, XContentType xContentType) throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a raw field with the given bytes as the value
|
* Writes a raw value taken from the bytes in the stream
|
||||||
* @deprecated use {@link #writeRawField(String, BytesReference, XContentType)} to avoid content type auto-detection
|
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
void writeRawValue(InputStream value, XContentType xContentType) throws IOException;
|
||||||
void writeRawField(String name, BytesReference value) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a raw field with the given bytes as the value
|
|
||||||
*/
|
|
||||||
void writeRawField(String name, BytesReference value, XContentType xContentType) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a value with the source coming directly from the bytes
|
|
||||||
* @deprecated use {@link #writeRawValue(BytesReference, XContentType)} to avoid content type auto-detection
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
void writeRawValue(BytesReference value) throws IOException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Writes a value with the source coming directly from the bytes
|
|
||||||
*/
|
|
||||||
void writeRawValue(BytesReference value, XContentType xContentType) throws IOException;
|
|
||||||
|
|
||||||
void copyCurrentStructure(XContentParser parser) throws IOException;
|
void copyCurrentStructure(XContentParser parser) throws IOException;
|
||||||
|
|
||||||
|
|
|
@ -28,9 +28,7 @@ import com.fasterxml.jackson.core.json.JsonWriteContext;
|
||||||
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
||||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
||||||
import com.fasterxml.jackson.core.util.JsonGeneratorDelegate;
|
import com.fasterxml.jackson.core.util.JsonGeneratorDelegate;
|
||||||
import org.elasticsearch.common.bytes.BytesReference;
|
|
||||||
import org.elasticsearch.common.io.Streams;
|
import org.elasticsearch.common.io.Streams;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
|
||||||
import org.elasticsearch.common.xcontent.DeprecationHandler;
|
import org.elasticsearch.common.xcontent.DeprecationHandler;
|
||||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||||
import org.elasticsearch.common.xcontent.XContent;
|
import org.elasticsearch.common.xcontent.XContent;
|
||||||
|
@ -333,51 +331,33 @@ public class JsonXContentGenerator implements XContentGenerator {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final void writeRawField(String name, BytesReference content) throws IOException {
|
public void writeRawValue(InputStream stream, XContentType xContentType) throws IOException {
|
||||||
XContentType contentType = XContentFactory.xContentType(content);
|
if (mayWriteRawData(xContentType) == false) {
|
||||||
if (contentType == null) {
|
copyRawValue(stream, xContentType.xContent());
|
||||||
throw new IllegalArgumentException("Can't write raw bytes whose xcontent-type can't be guessed");
|
|
||||||
}
|
|
||||||
writeRawField(name, content, contentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeRawField(String name, BytesReference content, XContentType contentType) throws IOException {
|
|
||||||
if (mayWriteRawData(contentType) == false) {
|
|
||||||
writeFieldName(name);
|
|
||||||
copyRawValue(content, contentType.xContent());
|
|
||||||
} else {
|
|
||||||
writeStartRaw(name);
|
|
||||||
flush();
|
|
||||||
content.writeTo(os);
|
|
||||||
writeEndRaw();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeRawValue(BytesReference content) throws IOException {
|
|
||||||
XContentType contentType = XContentFactory.xContentType(content);
|
|
||||||
if (contentType == null) {
|
|
||||||
throw new IllegalArgumentException("Can't write raw bytes whose xcontent-type can't be guessed");
|
|
||||||
}
|
|
||||||
writeRawValue(content, contentType);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void writeRawValue(BytesReference content, XContentType contentType) throws IOException {
|
|
||||||
if (mayWriteRawData(contentType) == false) {
|
|
||||||
copyRawValue(content, contentType.xContent());
|
|
||||||
} else {
|
} else {
|
||||||
if (generator.getOutputContext().getCurrentName() != null) {
|
if (generator.getOutputContext().getCurrentName() != null) {
|
||||||
// If we've just started a field we'll need to add the separator
|
// If we've just started a field we'll need to add the separator
|
||||||
generator.writeRaw(':');
|
generator.writeRaw(':');
|
||||||
}
|
}
|
||||||
flush();
|
flush();
|
||||||
content.writeTo(os);
|
transfer(stream, os);
|
||||||
writeEndRaw();
|
writeEndRaw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A basic copy of Java 9's InputStream#transferTo
|
||||||
|
private static long transfer(InputStream in, OutputStream out) throws IOException {
|
||||||
|
Objects.requireNonNull(out, "out");
|
||||||
|
long transferred = 0;
|
||||||
|
byte[] buffer = new byte[8192];
|
||||||
|
int read;
|
||||||
|
while ((read = in.read(buffer, 0, 8192)) >= 0) {
|
||||||
|
out.write(buffer, 0, read);
|
||||||
|
transferred += read;
|
||||||
|
}
|
||||||
|
return transferred;
|
||||||
|
}
|
||||||
|
|
||||||
private boolean mayWriteRawData(XContentType contentType) {
|
private boolean mayWriteRawData(XContentType contentType) {
|
||||||
// When the current generator is filtered (ie filter != null)
|
// When the current generator is filtered (ie filter != null)
|
||||||
// or the content is in a different format than the current generator,
|
// or the content is in a different format than the current generator,
|
||||||
|
@ -394,13 +374,12 @@ public class JsonXContentGenerator implements XContentGenerator {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void copyRawValue(BytesReference content, XContent xContent) throws IOException {
|
protected void copyRawValue(InputStream stream, XContent xContent) throws IOException {
|
||||||
// EMPTY is safe here because we never call namedObject
|
// EMPTY is safe here because we never call namedObject
|
||||||
try (StreamInput input = content.streamInput();
|
try (XContentParser parser = xContent
|
||||||
XContentParser parser = xContent
|
|
||||||
// It's okay to pass the throwing deprecation handler because we
|
// It's okay to pass the throwing deprecation handler because we
|
||||||
// should not be writing raw fields when generating JSON
|
// should not be writing raw fields when generating JSON
|
||||||
.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, input)) {
|
.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, stream)) {
|
||||||
copyCurrentStructure(parser);
|
copyCurrentStructure(parser);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,10 @@ import org.elasticsearch.action.ActionRequestValidationException;
|
||||||
import org.elasticsearch.action.get.GetRequest;
|
import org.elasticsearch.action.get.GetRequest;
|
||||||
import org.elasticsearch.action.get.GetResponse;
|
import org.elasticsearch.action.get.GetResponse;
|
||||||
import org.elasticsearch.client.node.NodeClient;
|
import org.elasticsearch.client.node.NodeClient;
|
||||||
|
import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.settings.Settings;
|
import org.elasticsearch.common.settings.Settings;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
import org.elasticsearch.rest.BaseRestHandler;
|
import org.elasticsearch.rest.BaseRestHandler;
|
||||||
import org.elasticsearch.rest.BytesRestResponse;
|
import org.elasticsearch.rest.BytesRestResponse;
|
||||||
import org.elasticsearch.rest.RestController;
|
import org.elasticsearch.rest.RestController;
|
||||||
|
@ -81,7 +83,8 @@ public class RestGetSourceAction extends BaseRestHandler {
|
||||||
if (response.isSourceEmpty()) {
|
if (response.isSourceEmpty()) {
|
||||||
return new BytesRestResponse(NOT_FOUND, builder);
|
return new BytesRestResponse(NOT_FOUND, builder);
|
||||||
} else {
|
} else {
|
||||||
builder.rawValue(response.getSourceInternal());
|
final BytesReference source = response.getSourceInternal();
|
||||||
|
builder.rawValue(source.streamInput(), XContentFactory.xContentType(source));
|
||||||
return new BytesRestResponse(OK, builder);
|
return new BytesRestResponse(OK, builder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,6 +24,7 @@ import org.elasticsearch.common.bytes.BytesReference;
|
||||||
import org.elasticsearch.common.io.stream.StreamInput;
|
import org.elasticsearch.common.io.stream.StreamInput;
|
||||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||||
|
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -57,7 +58,7 @@ public class RawTaskStatus implements Task.Status {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||||
return builder.rawValue(status);
|
return builder.rawValue(status.streamInput(), XContentFactory.xContentType(status));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -748,7 +748,7 @@ public abstract class BaseXContentTestCase extends ESTestCase {
|
||||||
if (useStream) {
|
if (useStream) {
|
||||||
generator.writeRawField("bar", new ByteArrayInputStream(rawData));
|
generator.writeRawField("bar", new ByteArrayInputStream(rawData));
|
||||||
} else {
|
} else {
|
||||||
generator.writeRawField("bar", new BytesArray(rawData));
|
generator.writeRawField("bar", new BytesArray(rawData).streamInput());
|
||||||
}
|
}
|
||||||
generator.writeEndObject();
|
generator.writeEndObject();
|
||||||
}
|
}
|
||||||
|
@ -785,7 +785,7 @@ public abstract class BaseXContentTestCase extends ESTestCase {
|
||||||
|
|
||||||
os = new ByteArrayOutputStream();
|
os = new ByteArrayOutputStream();
|
||||||
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
|
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
|
||||||
generator.writeRawValue(new BytesArray(rawData));
|
generator.writeRawValue(new BytesArray(rawData).streamInput(), source.type());
|
||||||
}
|
}
|
||||||
|
|
||||||
XContentParser parser = xcontentType().xContent()
|
XContentParser parser = xcontentType().xContent()
|
||||||
|
@ -801,7 +801,7 @@ public abstract class BaseXContentTestCase extends ESTestCase {
|
||||||
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
|
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
|
||||||
generator.writeStartObject();
|
generator.writeStartObject();
|
||||||
generator.writeFieldName("test");
|
generator.writeFieldName("test");
|
||||||
generator.writeRawValue(new BytesArray(rawData));
|
generator.writeRawValue(new BytesArray(rawData).streamInput(), source.type());
|
||||||
generator.writeEndObject();
|
generator.writeEndObject();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue