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
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
if (source != null) {
|
||||
builder.rawValue(new BytesArray(source), XContentType.JSON);
|
||||
builder.rawValue(new BytesArray(source).streamInput(), XContentType.JSON);
|
||||
} else {
|
||||
builder.startObject().endObject();
|
||||
}
|
||||
|
|
|
@ -987,7 +987,7 @@ public final class XContentBuilder implements Releasable, Flushable {
|
|||
*/
|
||||
@Deprecated
|
||||
public XContentBuilder rawField(String name, BytesReference value) throws IOException {
|
||||
generator.writeRawField(name, value);
|
||||
generator.writeRawField(name, value.streamInput());
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -995,25 +995,15 @@ public final class XContentBuilder implements Releasable, Flushable {
|
|||
* Writes a raw field with the given bytes as the value
|
||||
*/
|
||||
public XContentBuilder rawField(String name, BytesReference value, XContentType contentType) throws IOException {
|
||||
generator.writeRawField(name, value, contentType);
|
||||
generator.writeRawField(name, value.streamInput(), contentType);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes a value with the source coming directly from the bytes
|
||||
* @deprecated use {@link #rawValue(BytesReference, XContentType)} to avoid content type auto-detection
|
||||
* Writes a value with the source coming directly from the bytes in the stream
|
||||
*/
|
||||
@Deprecated
|
||||
public XContentBuilder rawValue(BytesReference value) throws IOException {
|
||||
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);
|
||||
public XContentBuilder rawValue(InputStream stream, XContentType contentType) throws IOException {
|
||||
generator.writeRawValue(stream, contentType);
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,6 @@
|
|||
|
||||
package org.elasticsearch.common.xcontent;
|
||||
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.io.Flushable;
|
||||
import java.io.IOException;
|
||||
|
@ -99,28 +97,9 @@ public interface XContentGenerator extends Closeable, Flushable {
|
|||
void writeRawField(String name, InputStream value, XContentType xContentType) throws IOException;
|
||||
|
||||
/**
|
||||
* Writes a raw field with the given bytes as the value
|
||||
* @deprecated use {@link #writeRawField(String, BytesReference, XContentType)} to avoid content type auto-detection
|
||||
* Writes a raw value taken from the bytes in the stream
|
||||
*/
|
||||
@Deprecated
|
||||
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 writeRawValue(InputStream value, XContentType xContentType) 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.DefaultPrettyPrinter;
|
||||
import com.fasterxml.jackson.core.util.JsonGeneratorDelegate;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.io.Streams;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.xcontent.DeprecationHandler;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.XContent;
|
||||
|
@ -333,51 +331,33 @@ public class JsonXContentGenerator implements XContentGenerator {
|
|||
}
|
||||
|
||||
@Override
|
||||
public final void writeRawField(String name, 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");
|
||||
}
|
||||
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());
|
||||
public void writeRawValue(InputStream stream, XContentType xContentType) throws IOException {
|
||||
if (mayWriteRawData(xContentType) == false) {
|
||||
copyRawValue(stream, xContentType.xContent());
|
||||
} else {
|
||||
if (generator.getOutputContext().getCurrentName() != null) {
|
||||
// If we've just started a field we'll need to add the separator
|
||||
generator.writeRaw(':');
|
||||
}
|
||||
flush();
|
||||
content.writeTo(os);
|
||||
transfer(stream, os);
|
||||
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) {
|
||||
// When the current generator is filtered (ie filter != null)
|
||||
// or the content is in a different format than the current generator,
|
||||
|
@ -394,13 +374,12 @@ public class JsonXContentGenerator implements XContentGenerator {
|
|||
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
|
||||
try (StreamInput input = content.streamInput();
|
||||
XContentParser parser = xContent
|
||||
try (XContentParser parser = xContent
|
||||
// It's okay to pass the throwing deprecation handler because we
|
||||
// should not be writing raw fields when generating JSON
|
||||
.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, input)) {
|
||||
.createParser(NamedXContentRegistry.EMPTY, DeprecationHandler.THROW_UNSUPPORTED_OPERATION, stream)) {
|
||||
copyCurrentStructure(parser);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,10 @@ import org.elasticsearch.action.ActionRequestValidationException;
|
|||
import org.elasticsearch.action.get.GetRequest;
|
||||
import org.elasticsearch.action.get.GetResponse;
|
||||
import org.elasticsearch.client.node.NodeClient;
|
||||
import org.elasticsearch.common.bytes.BytesReference;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
import org.elasticsearch.rest.BaseRestHandler;
|
||||
import org.elasticsearch.rest.BytesRestResponse;
|
||||
import org.elasticsearch.rest.RestController;
|
||||
|
@ -81,7 +83,8 @@ public class RestGetSourceAction extends BaseRestHandler {
|
|||
if (response.isSourceEmpty()) {
|
||||
return new BytesRestResponse(NOT_FOUND, builder);
|
||||
} else {
|
||||
builder.rawValue(response.getSourceInternal());
|
||||
final BytesReference source = response.getSourceInternal();
|
||||
builder.rawValue(source.streamInput(), XContentFactory.xContentType(source));
|
||||
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.StreamOutput;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
@ -57,7 +58,7 @@ public class RawTaskStatus implements Task.Status {
|
|||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
return builder.rawValue(status);
|
||||
return builder.rawValue(status.streamInput(), XContentFactory.xContentType(status));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -748,7 +748,7 @@ public abstract class BaseXContentTestCase extends ESTestCase {
|
|||
if (useStream) {
|
||||
generator.writeRawField("bar", new ByteArrayInputStream(rawData));
|
||||
} else {
|
||||
generator.writeRawField("bar", new BytesArray(rawData));
|
||||
generator.writeRawField("bar", new BytesArray(rawData).streamInput());
|
||||
}
|
||||
generator.writeEndObject();
|
||||
}
|
||||
|
@ -785,7 +785,7 @@ public abstract class BaseXContentTestCase extends ESTestCase {
|
|||
|
||||
os = new ByteArrayOutputStream();
|
||||
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
|
||||
generator.writeRawValue(new BytesArray(rawData));
|
||||
generator.writeRawValue(new BytesArray(rawData).streamInput(), source.type());
|
||||
}
|
||||
|
||||
XContentParser parser = xcontentType().xContent()
|
||||
|
@ -801,7 +801,7 @@ public abstract class BaseXContentTestCase extends ESTestCase {
|
|||
try (XContentGenerator generator = xcontentType().xContent().createGenerator(os)) {
|
||||
generator.writeStartObject();
|
||||
generator.writeFieldName("test");
|
||||
generator.writeRawValue(new BytesArray(rawData));
|
||||
generator.writeRawValue(new BytesArray(rawData).streamInput(), source.type());
|
||||
generator.writeEndObject();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue