diff --git a/driver-core/src/main/com/mongodb/internal/connection/AbstractByteBufBsonDocument.java b/driver-core/src/main/com/mongodb/internal/connection/AbstractByteBufBsonDocument.java deleted file mode 100644 index 4d344401fb9..00000000000 --- a/driver-core/src/main/com/mongodb/internal/connection/AbstractByteBufBsonDocument.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2008-present MongoDB, Inc. - * - * Licensed 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 com.mongodb.internal.connection; - -import com.mongodb.lang.Nullable; -import org.bson.BsonDocument; -import org.bson.BsonReader; -import org.bson.BsonValue; -import org.bson.codecs.BsonValueCodecProvider; -import org.bson.codecs.DecoderContext; -import org.bson.codecs.configuration.CodecRegistry; - -import java.util.Collection; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; - -import static com.mongodb.assertions.Assertions.assertNotNull; -import static com.mongodb.assertions.Assertions.notNull; -import static org.bson.codecs.BsonValueCodecProvider.getClassForBsonType; -import static org.bson.codecs.configuration.CodecRegistries.fromProviders; - -abstract class AbstractByteBufBsonDocument extends BsonDocument { - private static final long serialVersionUID = 1L; - private static final CodecRegistry REGISTRY = fromProviders(new BsonValueCodecProvider()); - - @Override - public void clear() { - throw new UnsupportedOperationException("ByteBufBsonDocument instances are immutable"); - } - - @Override - public BsonValue put(final String key, final BsonValue value) { - throw new UnsupportedOperationException("ByteBufBsonDocument instances are immutable"); - } - - @Override - public BsonDocument append(final String key, final BsonValue value) { - throw new UnsupportedOperationException("ByteBufBsonDocument instances are immutable"); - } - - @Override - public void putAll(final Map m) { - throw new UnsupportedOperationException("ByteBufBsonDocument instances are immutable"); - } - - @Override - public BsonValue remove(final Object key) { - throw new UnsupportedOperationException("ByteBufBsonDocument instances are immutable"); - } - - @Override - public boolean isEmpty() { - return assertNotNull(findInDocument(new Finder() { - @Override - public Boolean find(final BsonReader bsonReader) { - return false; - } - - @Override - public Boolean notFound() { - return true; - } - })); - } - - @Override - public int size() { - return assertNotNull(findInDocument(new Finder() { - private int size; - - @Override - @Nullable - public Integer find(final BsonReader bsonReader) { - size++; - bsonReader.readName(); - bsonReader.skipValue(); - return null; - } - - @Override - public Integer notFound() { - return size; - } - })); - } - - @Override - public Set> entrySet() { - return toBaseBsonDocument().entrySet(); - } - - @Override - public Collection values() { - return toBaseBsonDocument().values(); - } - - @Override - public Set keySet() { - return toBaseBsonDocument().keySet(); - } - - @Override - public boolean containsKey(final Object key) { - if (key == null) { - throw new IllegalArgumentException("key can not be null"); - } - - Boolean containsKey = findInDocument(new Finder() { - @Override - public Boolean find(final BsonReader bsonReader) { - if (bsonReader.readName().equals(key)) { - return true; - } - bsonReader.skipValue(); - return null; - } - - @Override - public Boolean notFound() { - return false; - } - }); - return containsKey != null ? containsKey : false; - } - - @Override - public boolean containsValue(final Object value) { - Boolean containsValue = findInDocument(new Finder() { - @Override - public Boolean find(final BsonReader bsonReader) { - bsonReader.skipName(); - if (deserializeBsonValue(bsonReader).equals(value)) { - return true; - } - return null; - } - - @Override - public Boolean notFound() { - return false; - } - }); - return containsValue != null ? containsValue : false; - } - - @Nullable - @Override - public BsonValue get(final Object key) { - notNull("key", key); - return findInDocument(new Finder() { - @Override - public BsonValue find(final BsonReader bsonReader) { - if (bsonReader.readName().equals(key)) { - return deserializeBsonValue(bsonReader); - } - bsonReader.skipValue(); - return null; - } - - @Nullable - @Override - public BsonValue notFound() { - return null; - } - }); - } - - /** - * Gets the first key in this document. - * - * @return the first key in this document - * @throws java.util.NoSuchElementException if the document is empty - */ - public String getFirstKey() { - return assertNotNull(findInDocument(new Finder() { - @Override - public String find(final BsonReader bsonReader) { - return bsonReader.readName(); - } - - @Override - public String notFound() { - throw new NoSuchElementException(); - } - })); - } - - interface Finder { - @Nullable - T find(BsonReader bsonReader); - @Nullable - T notFound(); - } - - @Nullable abstract T findInDocument(Finder finder); - - //AbstractBsonReader getBsonReader(); - - abstract BsonDocument toBaseBsonDocument(); - - @Override - public boolean equals(final Object o) { - if (this == o) { - return true; - } - return toBaseBsonDocument().equals(o); - } - - @Override - public int hashCode() { - return toBaseBsonDocument().hashCode(); - } - - private BsonValue deserializeBsonValue(final BsonReader bsonReader) { - return REGISTRY.get(getClassForBsonType(bsonReader.getCurrentBsonType())).decode(bsonReader, DecoderContext.builder().build()); - } - - // see https://docs.oracle.com/javase/6/docs/platform/serialization/spec/output.html - Object writeReplace() { - return toBaseBsonDocument(); - } - -} diff --git a/driver-core/src/main/com/mongodb/internal/connection/ByteBufBsonDocument.java b/driver-core/src/main/com/mongodb/internal/connection/ByteBufBsonDocument.java index 163a1c4e99b..676dba2d78c 100644 --- a/driver-core/src/main/com/mongodb/internal/connection/ByteBufBsonDocument.java +++ b/driver-core/src/main/com/mongodb/internal/connection/ByteBufBsonDocument.java @@ -21,11 +21,13 @@ import org.bson.BsonDocument; import org.bson.BsonReader; import org.bson.BsonType; +import org.bson.BsonValue; import org.bson.ByteBuf; -import org.bson.ByteBufNIO; import org.bson.RawBsonDocument; import org.bson.codecs.BsonDocumentCodec; +import org.bson.codecs.BsonValueCodecProvider; import org.bson.codecs.DecoderContext; +import org.bson.codecs.configuration.CodecRegistry; import org.bson.io.ByteBufferBsonInput; import org.bson.json.JsonMode; import org.bson.json.JsonWriter; @@ -34,31 +36,24 @@ import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.StringWriter; -import java.nio.ByteOrder; import java.util.ArrayList; +import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; -class ByteBufBsonDocument extends AbstractByteBufBsonDocument { +import static com.mongodb.assertions.Assertions.assertNotNull; +import static com.mongodb.assertions.Assertions.notNull; +import static org.bson.codecs.BsonValueCodecProvider.getClassForBsonType; +import static org.bson.codecs.configuration.CodecRegistries.fromProviders; + +final class ByteBufBsonDocument extends BsonDocument { private static final long serialVersionUID = 2L; - private final transient ByteBuf byteBuf; + private static final CodecRegistry REGISTRY = fromProviders(new BsonValueCodecProvider()); - static List createList(final ResponseBuffers responseBuffers) { - int numDocuments = responseBuffers.getReplyHeader().getNumberReturned(); - ByteBuf documentsBuffer = responseBuffers.getBodyByteBuffer(); - documentsBuffer.order(ByteOrder.LITTLE_ENDIAN); - List documents = new ArrayList<>(numDocuments); - while (documents.size() < numDocuments) { - int documentSizeInBytes = documentsBuffer.getInt(); - documentsBuffer.position(documentsBuffer.position() - 4); - ByteBuf documentBuffer = documentsBuffer.duplicate(); - documentBuffer.limit(documentBuffer.position() + documentSizeInBytes); - documents.add(new ByteBufBsonDocument(new ByteBufNIO(documentBuffer.asNIO()))); - documentBuffer.release(); - documentsBuffer.position(documentsBuffer.position() + documentSizeInBytes); - } - return documents; - } + private final transient ByteBuf byteBuf; static List createList(final ByteBufferBsonOutput bsonOutput, final int startPosition) { List duplicateByteBuffers = bsonOutput.getByteBuffers(); @@ -118,6 +113,14 @@ public BsonReader asBsonReader() { return new BsonBinaryReader(new ByteBufferBsonInput(byteBuf.duplicate())); } + @SuppressWarnings("MethodDoesntCallSuperMethod") + @Override + public BsonDocument clone() { + byte[] clonedBytes = new byte[byteBuf.remaining()]; + byteBuf.get(byteBuf.position(), clonedBytes); + return new RawBsonDocument(clonedBytes); + } + @Nullable T findInDocument(final Finder finder) { ByteBuf duplicateByteBuf = byteBuf.duplicate(); @@ -137,13 +140,6 @@ T findInDocument(final Finder finder) { return finder.notFound(); } - @Override - public BsonDocument clone() { - byte[] clonedBytes = new byte[byteBuf.remaining()]; - byteBuf.get(byteBuf.position(), clonedBytes); - return new RawBsonDocument(clonedBytes); - } - int getSizeInBytes() { return byteBuf.getInt(byteBuf.position()); } @@ -161,6 +157,184 @@ BsonDocument toBaseBsonDocument() { this.byteBuf = byteBuf; } + @Override + public void clear() { + throw new UnsupportedOperationException("ByteBufBsonDocument instances are immutable"); + } + + @Override + public BsonValue put(final String key, final BsonValue value) { + throw new UnsupportedOperationException("ByteBufBsonDocument instances are immutable"); + } + + @Override + public BsonDocument append(final String key, final BsonValue value) { + throw new UnsupportedOperationException("ByteBufBsonDocument instances are immutable"); + } + + @Override + public void putAll(final Map m) { + throw new UnsupportedOperationException("ByteBufBsonDocument instances are immutable"); + } + + @Override + public BsonValue remove(final Object key) { + throw new UnsupportedOperationException("ByteBufBsonDocument instances are immutable"); + } + + @Override + public boolean isEmpty() { + return assertNotNull(findInDocument(new Finder() { + @Override + public Boolean find(final BsonReader bsonReader) { + return false; + } + + @Override + public Boolean notFound() { + return true; + } + })); + } + + @Override + public int size() { + return assertNotNull(findInDocument(new Finder() { + private int size; + + @Override + @Nullable + public Integer find(final BsonReader bsonReader) { + size++; + bsonReader.readName(); + bsonReader.skipValue(); + return null; + } + + @Override + public Integer notFound() { + return size; + } + })); + } + + @Override + public Set> entrySet() { + return toBaseBsonDocument().entrySet(); + } + + @Override + public Collection values() { + return toBaseBsonDocument().values(); + } + + @Override + public Set keySet() { + return toBaseBsonDocument().keySet(); + } + + @Override + public boolean containsKey(final Object key) { + if (key == null) { + throw new IllegalArgumentException("key can not be null"); + } + + Boolean containsKey = findInDocument(new Finder() { + @Override + public Boolean find(final BsonReader bsonReader) { + if (bsonReader.readName().equals(key)) { + return true; + } + bsonReader.skipValue(); + return null; + } + + @Override + public Boolean notFound() { + return false; + } + }); + return containsKey != null ? containsKey : false; + } + + @Override + public boolean containsValue(final Object value) { + Boolean containsValue = findInDocument(new Finder() { + @Override + public Boolean find(final BsonReader bsonReader) { + bsonReader.skipName(); + if (deserializeBsonValue(bsonReader).equals(value)) { + return true; + } + return null; + } + + @Override + public Boolean notFound() { + return false; + } + }); + return containsValue != null ? containsValue : false; + } + + @Nullable + @Override + public BsonValue get(final Object key) { + notNull("key", key); + return findInDocument(new Finder() { + @Override + public BsonValue find(final BsonReader bsonReader) { + if (bsonReader.readName().equals(key)) { + return deserializeBsonValue(bsonReader); + } + bsonReader.skipValue(); + return null; + } + + @Nullable + @Override + public BsonValue notFound() { + return null; + } + }); + } + + /** + * Gets the first key in this document. + * + * @return the first key in this document + * @throws java.util.NoSuchElementException if the document is empty + */ + public String getFirstKey() { + return assertNotNull(findInDocument(new Finder() { + @Override + public String find(final BsonReader bsonReader) { + return bsonReader.readName(); + } + + @Override + public String notFound() { + throw new NoSuchElementException(); + } + })); + } + + private interface Finder { + @Nullable + T find(BsonReader bsonReader); + @Nullable + T notFound(); + } + + private BsonValue deserializeBsonValue(final BsonReader bsonReader) { + return REGISTRY.get(getClassForBsonType(bsonReader.getCurrentBsonType())).decode(bsonReader, DecoderContext.builder().build()); + } + + // see https://docs.oracle.com/javase/6/docs/platform/serialization/spec/output.html + private Object writeReplace() { + return toBaseBsonDocument(); + } + // see https://docs.oracle.com/javase/6/docs/platform/serialization/spec/input.html private void readObject(final ObjectInputStream stream) throws InvalidObjectException { throw new InvalidObjectException("Proxy required");