From 59ea719566a6df47309a1696af3629a545f17d24 Mon Sep 17 00:00:00 2001 From: bvanalderweireldt Date: Sun, 28 Feb 2016 18:09:57 -0600 Subject: [PATCH] SOLR-7516 add asserts and Improve Javadoc comments (patch from gerlowskija) --- .../apache/solr/common/util/JavaBinCodec.java | 59 ++++++++++++++----- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java b/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java index b90fb7ea1dde..7864eb6816d6 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/JavaBinCodec.java @@ -40,14 +40,17 @@ import org.noggit.CharArr; /** - * The class is designed to optimaly serialize/deserialize any supported types in Solr response. As we know there are only a limited type of - * items this class can do it with very minimal amount of payload and code. There are 15 known types and if there is an - * object in the object tree which does not fall into these types, It must be converted to one of these. Implement an - * ObjectResolver and pass it over It is expected that this class is used on both end of the pipes. The class has one - * read method and one write method for each of the datatypes + * Defines a space-efficient serialization/deserialization format for transferring data. *

- * Note -- Never re-use an instance of this class for more than one marshal or unmarshall operation. Always create a new - * instance. + * JavaBinCodec has built in support many commonly used types. This includes primitive types (boolean, byte, short, double, int, long, + * float), common Java containers/utilities (Date, Map, Collection, Iterator, String, Object[], byte[]), and frequently used Solr types + * ({@link NamedList}, {@link SolrDocument}, {@link SolrDocumentList}). Each of the above types has a pair of associated methods which + * read and write that type to a stream. + *

+ * Classes that aren't supported natively can still be serialized/deserialized by providing an {@link JavaBinCodec.ObjectResolver} object + * that knows how to work with the unsupported class. This allows {@link JavaBinCodec} to be used to marshall/unmarshall arbitrary content. + *

+ * NOTE -- {@link JavaBinCodec} instances cannot be reused for more than one marshall or unmarshall operation. */ public class JavaBinCodec { @@ -94,6 +97,8 @@ public class JavaBinCodec { protected FastOutputStream daos; private StringCache stringCache; private WritableDocFields writableDocFields; + private boolean alreadyMarshalled; + private boolean alreadyUnmarshalled; public JavaBinCodec() { resolver =null; @@ -103,28 +108,31 @@ public JavaBinCodec() { public JavaBinCodec(ObjectResolver resolver) { this(resolver, null); } - public JavaBinCodec setWritableDocFields(WritableDocFields writableDocFields){ - this.writableDocFields = writableDocFields; - return this; - - } public JavaBinCodec(ObjectResolver resolver, StringCache stringCache) { this.resolver = resolver; this.stringCache = stringCache; } + + public JavaBinCodec setWritableDocFields(WritableDocFields writableDocFields){ + this.writableDocFields = writableDocFields; + return this; + + } public ObjectResolver getResolver() { return resolver; } public void marshal(Object nl, OutputStream os) throws IOException { + assert !alreadyMarshalled; init(FastOutputStream.wrap(os)); try { daos.writeByte(VERSION); writeVal(nl); } finally { daos.flushBuffer(); + alreadyMarshalled = true; } } @@ -136,12 +144,15 @@ public void init(FastOutputStream os) { byte version; public Object unmarshal(InputStream is) throws IOException { + assert !alreadyUnmarshalled; FastInputStream dis = FastInputStream.wrap(is); version = dis.readByte(); if (version != VERSION) { throw new RuntimeException("Invalid version (expected " + VERSION + ", but " + version + ") or the data in not in 'javabin' format"); } + + alreadyUnmarshalled = true; return readVal(dis); } @@ -271,8 +282,16 @@ public Object readVal(DataInputInputStream dis) throws IOException { throw new RuntimeException("Unknown type " + tagByte); } + /** + * Determine the instance type of Object 'val' and call the appropriate write function for it. + * + * @param val + * @return true if the object type is compatible + * @throws IOException + */ public boolean writeKnownType(Object val) throws IOException { if (writePrimitive(val)) return true; + if (val instanceof NamedList) { writeNamedList((NamedList) val); return true; @@ -282,7 +301,7 @@ public boolean writeKnownType(Object val) throws IOException { return true; } if (val instanceof Collection) { - writeArray((Collection) val); + writeArray((Collection) val); return true; } if (val instanceof Object[]) { @@ -879,8 +898,20 @@ public String readExternString(DataInputInputStream fis) throws IOException { } } - + /** + * Allows extension of {@link JavaBinCodec} to support serialization of arbitrary data types. + *

+ * Implementors of this interface write a method to serialize a given object using an existing {@link JavaBinCodec} + */ public static interface ObjectResolver { + /** + * Examine and attempt to serialize the given object, using a {@link JavaBinCodec} to write it to a stream. + * + * @param o the object that the caller wants serialized. + * @param codec used to actually serialize {@code o}. + * @return any pieces of {@code o} that were unable to be serialized, or {@code null} if the whole object was successfully serialized. + * @see JavaBinCodec + */ public Object resolve(Object o, JavaBinCodec codec) throws IOException; }