org.elasticsearch.common.io.stream.StreamOutput Maven / Gradle / Ivy
The newest version!
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.common.io.stream;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexFormatTooNewException;
import org.apache.lucene.index.IndexFormatTooOldException;
import org.apache.lucene.store.AlreadyClosedException;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefBuilder;
import org.elasticsearch.ElasticsearchException;
import org.elasticsearch.Version;
import org.elasticsearch.common.Nullable;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.functionscore.ScoreFunctionBuilder;
import org.elasticsearch.search.rescore.RescoreBuilder;
import org.elasticsearch.tasks.Task;
import org.joda.time.ReadableInstant;
import java.io.EOFException;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.NoSuchFileException;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
/**
*
*/
public abstract class StreamOutput extends OutputStream {
private Version version = Version.CURRENT;
public Version getVersion() {
return this.version;
}
public StreamOutput setVersion(Version version) {
this.version = version;
return this;
}
public long position() throws IOException {
throw new UnsupportedOperationException();
}
public void seek(long position) throws IOException {
throw new UnsupportedOperationException();
}
/**
* Writes a single byte.
*/
public abstract void writeByte(byte b) throws IOException;
/**
* Writes an array of bytes.
*
* @param b the bytes to write
*/
public void writeBytes(byte[] b) throws IOException {
writeBytes(b, 0, b.length);
}
/**
* Writes an array of bytes.
*
* @param b the bytes to write
* @param length the number of bytes to write
*/
public void writeBytes(byte[] b, int length) throws IOException {
writeBytes(b, 0, length);
}
/**
* Writes an array of bytes.
*
* @param b the bytes to write
* @param offset the offset in the byte array
* @param length the number of bytes to write
*/
public abstract void writeBytes(byte[] b, int offset, int length) throws IOException;
/**
* Writes an array of bytes.
*
* @param b the bytes to write
*/
public void writeByteArray(byte[] b) throws IOException {
writeVInt(b.length);
writeBytes(b, 0, b.length);
}
/**
* Writes the bytes reference, including a length header.
*/
public void writeBytesReference(@Nullable BytesReference bytes) throws IOException {
if (bytes == null) {
writeVInt(0);
return;
}
writeVInt(bytes.length());
bytes.writeTo(this);
}
public void writeBytesRef(BytesRef bytes) throws IOException {
if (bytes == null) {
writeVInt(0);
return;
}
writeVInt(bytes.length);
write(bytes.bytes, bytes.offset, bytes.length);
}
public final void writeShort(short v) throws IOException {
writeByte((byte) (v >> 8));
writeByte((byte) v);
}
/**
* Writes an int as four bytes.
*/
public void writeInt(int i) throws IOException {
writeByte((byte) (i >> 24));
writeByte((byte) (i >> 16));
writeByte((byte) (i >> 8));
writeByte((byte) i);
}
/**
* Writes an int in a variable-length format. Writes between one and
* five bytes. Smaller values take fewer bytes. Negative numbers
* will always use all 5 bytes and are therefore better serialized
* using {@link #writeInt}
*/
public void writeVInt(int i) throws IOException {
while ((i & ~0x7F) != 0) {
writeByte((byte) ((i & 0x7f) | 0x80));
i >>>= 7;
}
writeByte((byte) i);
}
/**
* Writes a long as eight bytes.
*/
public void writeLong(long i) throws IOException {
writeInt((int) (i >> 32));
writeInt((int) i);
}
/**
* Writes an long in a variable-length format. Writes between one and nine
* bytes. Smaller values take fewer bytes. Negative numbers are not
* supported.
*/
public void writeVLong(long i) throws IOException {
assert i >= 0;
while ((i & ~0x7F) != 0) {
writeByte((byte) ((i & 0x7f) | 0x80));
i >>>= 7;
}
writeByte((byte) i);
}
public void writeOptionalString(@Nullable String str) throws IOException {
if (str == null) {
writeBoolean(false);
} else {
writeBoolean(true);
writeString(str);
}
}
public void writeOptionalVInt(@Nullable Integer integer) throws IOException {
if (integer == null) {
writeBoolean(false);
} else {
writeBoolean(true);
writeVInt(integer);
}
}
public void writeOptionalText(@Nullable Text text) throws IOException {
if (text == null) {
writeInt(-1);
} else {
writeText(text);
}
}
private final BytesRefBuilder spare = new BytesRefBuilder();
public void writeText(Text text) throws IOException {
if (!text.hasBytes()) {
final String string = text.string();
spare.copyChars(string);
writeInt(spare.length());
write(spare.bytes(), 0, spare.length());
} else {
BytesReference bytes = text.bytes();
writeInt(bytes.length());
bytes.writeTo(this);
}
}
public void writeString(String str) throws IOException {
int charCount = str.length();
writeVInt(charCount);
int c;
for (int i = 0; i < charCount; i++) {
c = str.charAt(i);
if (c <= 0x007F) {
writeByte((byte) c);
} else if (c > 0x07FF) {
writeByte((byte) (0xE0 | c >> 12 & 0x0F));
writeByte((byte) (0x80 | c >> 6 & 0x3F));
writeByte((byte) (0x80 | c >> 0 & 0x3F));
} else {
writeByte((byte) (0xC0 | c >> 6 & 0x1F));
writeByte((byte) (0x80 | c >> 0 & 0x3F));
}
}
}
public void writeFloat(float v) throws IOException {
writeInt(Float.floatToIntBits(v));
}
public void writeDouble(double v) throws IOException {
writeLong(Double.doubleToLongBits(v));
}
private static byte ZERO = 0;
private static byte ONE = 1;
private static byte TWO = 2;
/**
* Writes a boolean.
*/
public void writeBoolean(boolean b) throws IOException {
writeByte(b ? ONE : ZERO);
}
public void writeOptionalBoolean(@Nullable Boolean b) throws IOException {
if (b == null) {
writeByte(TWO);
} else {
writeByte(b ? ONE : ZERO);
}
}
/**
* Forces any buffered output to be written.
*/
@Override
public abstract void flush() throws IOException;
/**
* Closes this stream to further operations.
*/
@Override
public abstract void close() throws IOException;
public abstract void reset() throws IOException;
@Override
public void write(int b) throws IOException {
writeByte((byte) b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
writeBytes(b, off, len);
}
public void writeStringArray(String[] array) throws IOException {
writeVInt(array.length);
for (String s : array) {
writeString(s);
}
}
/**
* Writes a string array, for nullable string, writes it as 0 (empty string).
*/
public void writeStringArrayNullable(@Nullable String[] array) throws IOException {
if (array == null) {
writeVInt(0);
} else {
writeVInt(array.length);
for (String s : array) {
writeString(s);
}
}
}
public void writeMap(@Nullable Map map) throws IOException {
writeGenericValue(map);
}
public void writeGenericValue(@Nullable Object value) throws IOException {
if (value == null) {
writeByte((byte) -1);
return;
}
Class type = value.getClass();
if (type == String.class) {
writeByte((byte) 0);
writeString((String) value);
} else if (type == Integer.class) {
writeByte((byte) 1);
writeInt((Integer) value);
} else if (type == Long.class) {
writeByte((byte) 2);
writeLong((Long) value);
} else if (type == Float.class) {
writeByte((byte) 3);
writeFloat((Float) value);
} else if (type == Double.class) {
writeByte((byte) 4);
writeDouble((Double) value);
} else if (type == Boolean.class) {
writeByte((byte) 5);
writeBoolean((Boolean) value);
} else if (type == byte[].class) {
writeByte((byte) 6);
writeVInt(((byte[]) value).length);
writeBytes(((byte[]) value));
} else if (value instanceof List) {
writeByte((byte) 7);
List list = (List) value;
writeVInt(list.size());
for (Object o : list) {
writeGenericValue(o);
}
} else if (value instanceof Object[]) {
writeByte((byte) 8);
Object[] list = (Object[]) value;
writeVInt(list.length);
for (Object o : list) {
writeGenericValue(o);
}
} else if (value instanceof Map) {
if (value instanceof LinkedHashMap) {
writeByte((byte) 9);
} else {
writeByte((byte) 10);
}
@SuppressWarnings("unchecked")
Map map = (Map) value;
writeVInt(map.size());
for (Map.Entry entry : map.entrySet()) {
writeString(entry.getKey());
writeGenericValue(entry.getValue());
}
} else if (type == Byte.class) {
writeByte((byte) 11);
writeByte((Byte) value);
} else if (type == Date.class) {
writeByte((byte) 12);
writeLong(((Date) value).getTime());
} else if (value instanceof ReadableInstant) {
writeByte((byte) 13);
writeString(((ReadableInstant) value).getZone().getID());
writeLong(((ReadableInstant) value).getMillis());
} else if (value instanceof BytesReference) {
writeByte((byte) 14);
writeBytesReference((BytesReference) value);
} else if (value instanceof Text) {
writeByte((byte) 15);
writeText((Text) value);
} else if (type == Short.class) {
writeByte((byte) 16);
writeShort((Short) value);
} else if (type == int[].class) {
writeByte((byte) 17);
writeIntArray((int[]) value);
} else if (type == long[].class) {
writeByte((byte) 18);
writeLongArray((long[]) value);
} else if (type == float[].class) {
writeByte((byte) 19);
writeFloatArray((float[]) value);
} else if (type == double[].class) {
writeByte((byte) 20);
writeDoubleArray((double[]) value);
} else if (value instanceof BytesRef) {
writeByte((byte) 21);
writeBytesRef((BytesRef) value);
} else if (type == GeoPoint.class) {
writeByte((byte) 22);
writeGeoPoint((GeoPoint) value);
} else {
throw new IOException("Can't write type [" + type + "]");
}
}
public void writeIntArray(int[] values) throws IOException {
writeVInt(values.length);
for (int value : values) {
writeInt(value);
}
}
public void writeVIntArray(int[] values) throws IOException {
writeVInt(values.length);
for (int value : values) {
writeVInt(value);
}
}
public void writeLongArray(long[] values) throws IOException {
writeVInt(values.length);
for (long value : values) {
writeLong(value);
}
}
public void writeVLongArray(long[] values) throws IOException {
writeVInt(values.length);
for (long value : values) {
writeVLong(value);
}
}
public void writeFloatArray(float[] values) throws IOException {
writeVInt(values.length);
for (float value : values) {
writeFloat(value);
}
}
public void writeDoubleArray(double[] values) throws IOException {
writeVInt(values.length);
for (double value : values) {
writeDouble(value);
}
}
/**
* Serializes a potential null value.
*/
public void writeOptionalStreamable(@Nullable Streamable streamable) throws IOException {
if (streamable != null) {
writeBoolean(true);
streamable.writeTo(this);
} else {
writeBoolean(false);
}
}
public void writeThrowable(Throwable throwable) throws IOException {
if (throwable == null) {
writeBoolean(false);
} else {
writeBoolean(true);
boolean writeCause = true;
boolean writeMessage = true;
if (throwable instanceof CorruptIndexException) {
writeVInt(1);
writeOptionalString(((CorruptIndexException)throwable).getOriginalMessage());
writeOptionalString(((CorruptIndexException)throwable).getResourceDescription());
writeMessage = false;
} else if (throwable instanceof IndexFormatTooNewException) {
writeVInt(2);
writeOptionalString(((IndexFormatTooNewException)throwable).getResourceDescription());
writeInt(((IndexFormatTooNewException)throwable).getVersion());
writeInt(((IndexFormatTooNewException)throwable).getMinVersion());
writeInt(((IndexFormatTooNewException)throwable).getMaxVersion());
writeMessage = false;
writeCause = false;
} else if (throwable instanceof IndexFormatTooOldException) {
writeVInt(3);
IndexFormatTooOldException t = (IndexFormatTooOldException) throwable;
writeOptionalString(t.getResourceDescription());
if (t.getVersion() == null) {
writeBoolean(false);
writeOptionalString(t.getReason());
} else {
writeBoolean(true);
writeInt(t.getVersion());
writeInt(t.getMinVersion());
writeInt(t.getMaxVersion());
}
writeMessage = false;
writeCause = false;
} else if (throwable instanceof NullPointerException) {
writeVInt(4);
writeCause = false;
} else if (throwable instanceof NumberFormatException) {
writeVInt(5);
writeCause = false;
} else if (throwable instanceof IllegalArgumentException) {
writeVInt(6);
} else if (throwable instanceof AlreadyClosedException) {
writeVInt(7);
} else if (throwable instanceof EOFException) {
writeVInt(8);
writeCause = false;
} else if (throwable instanceof SecurityException) {
writeVInt(9);
} else if (throwable instanceof StringIndexOutOfBoundsException) {
writeVInt(10);
writeCause = false;
} else if (throwable instanceof ArrayIndexOutOfBoundsException) {
writeVInt(11);
writeCause = false;
} else if (throwable instanceof AssertionError) {
writeVInt(12);
} else if (throwable instanceof FileNotFoundException) {
writeVInt(13);
writeCause = false;
} else if (throwable instanceof NoSuchFileException) {
writeVInt(14);
writeOptionalString(((NoSuchFileException) throwable).getFile());
writeOptionalString(((NoSuchFileException) throwable).getOtherFile());
writeOptionalString(((NoSuchFileException) throwable).getReason());
writeCause = false;
} else if (throwable instanceof OutOfMemoryError) {
writeVInt(15);
writeCause = false;
} else if (throwable instanceof IllegalStateException) {
writeVInt(16);
} else if (throwable instanceof LockObtainFailedException) {
writeVInt(17);
} else if (throwable instanceof InterruptedException) {
writeVInt(18);
writeCause = false;
} else {
ElasticsearchException ex;
if (throwable instanceof ElasticsearchException && ElasticsearchException.isRegistered(throwable.getClass())) {
ex = (ElasticsearchException) throwable;
} else {
ex = new NotSerializableExceptionWrapper(throwable);
}
writeVInt(0);
writeVInt(ElasticsearchException.getId(ex.getClass()));
ex.writeTo(this);
return;
}
if (writeMessage) {
writeOptionalString(throwable.getMessage());
}
if (writeCause) {
writeThrowable(throwable.getCause());
}
ElasticsearchException.writeStackTraces(throwable, this);
}
}
/**
* Writes a {@link NamedWriteable} to the current stream, by first writing its name and then the object itself
*/
void writeNamedWriteable(NamedWriteable namedWriteable) throws IOException {
writeString(namedWriteable.getWriteableName());
namedWriteable.writeTo(this);
}
/**
* Writes a {@link Task.Status} to the current stream.
*/
public void writeTaskStatus(Task.Status status) throws IOException {
writeNamedWriteable(status);
}
/**
* Writes the given {@link GeoPoint} to the stream
*/
public void writeGeoPoint(GeoPoint geoPoint) throws IOException {
writeDouble(geoPoint.lat());
writeDouble(geoPoint.lon());
}
/**
* Writes a list of {@link Writeable} objects
*/
public > void writeList(List list) throws IOException {
writeVInt(list.size());
for (T obj: list) {
obj.writeTo(this);
}
}
}