org.infinispan.schematic.internal.document.BsonReader Maven / Gradle / Ivy
/*
* ModeShape (http://www.modeshape.org)
*
* 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 org.infinispan.schematic.internal.document;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.UUID;
import org.infinispan.schematic.document.Array;
import org.infinispan.schematic.document.Bson;
import org.infinispan.schematic.document.Bson.BinaryType;
import org.infinispan.schematic.document.Document;
import org.infinispan.schematic.document.MaxKey;
import org.infinispan.schematic.document.MinKey;
import org.infinispan.schematic.document.ThreadSafe;
import org.infinispan.schematic.internal.io.BsonDataInput;
/**
* A component that reads BSON representations and constructs the in-memory {@link Document} representation.
*
* @author Randall Hauch (C) 2011 Red Hat Inc.
*/
@ThreadSafe
public class BsonReader {
protected static final DocumentValueFactory VALUE_FACTORY = new DefaultDocumentValueFactory();
/**
* Read the binary BSON representation from supplied input stream and construct the {@link Document} representation.
*
* @param stream the input stream; may not be null
* @return the in-memory {@link Document} representation
* @throws IOException if there was a problem reading from the stream
*/
public Document read( InputStream stream ) throws IOException {
// Create an object so that this reader is thread safe ...
DocumentValueFactory valueFactory = VALUE_FACTORY;
Reader reader = new Reader(new BsonDataInput(new DataInputStream(stream)), valueFactory);
reader.startDocument();
return reader.endDocument();
}
/**
* Read the binary BSON representation from supplied input stream and construct the {@link Document} representation.
*
* @param input the input stream; may not be null
* @return the in-memory {@link Document} representation
* @throws IOException if there was a problem reading from the stream
*/
public Document read( DataInput input ) throws IOException {
// Create an object so that this reader is thread safe ...
DocumentValueFactory valueFactory = VALUE_FACTORY;
Reader reader = new Reader(new BsonDataInput(input), valueFactory);
reader.startDocument();
return reader.endDocument();
}
/**
* Read the binary BSON representation from supplied input stream and construct the {@link Array} representation.
*
* @param stream the input stream; may not be null
* @return the in-memory {@link Document} representation
* @throws IOException if there was a problem reading from the stream
*/
public Array readArray( InputStream stream ) throws IOException {
// Create an object so that this reader is thread safe ...
DocumentValueFactory valueFactory = VALUE_FACTORY;
Reader reader = new Reader(new BsonDataInput(new DataInputStream(stream)), valueFactory);
reader.startArray();
return (Array)reader.endDocument();
}
/**
* Read the binary BSON representation from supplied input stream and construct the {@link Document} representation.
*
* @param input the input stream; may not be null
* @return the in-memory {@link Document} representation
* @throws IOException if there was a problem reading from the stream
*/
public Array readArray( DataInput input ) throws IOException {
// Create an object so that this reader is thread safe ...
DocumentValueFactory valueFactory = VALUE_FACTORY;
Reader reader = new Reader(new BsonDataInput(input), valueFactory);
reader.startArray();
return (Array)reader.endDocument();
}
protected static class Reader {
private final BsonDataInput data;
private MutableDocument object;
private DocumentValueFactory values;
// private final BsonEditor editor;
protected Reader( BsonDataInput data,
DocumentValueFactory valueFactory ) {
this.data = data;
this.values = valueFactory;
}
protected void startDocument() throws IOException {
object = readDocument(false);
}
protected void startArray() throws IOException {
object = readDocument(true);
}
protected MutableDocument readDocument( boolean array ) throws IOException {
// Read the size int32, but we don't care about the value 'cuz it's in bytes ...
int length = data.readInt();
int startingIndex = data.getTotalBytesRead();
int endingIndex = startingIndex + length;
MutableDocument doc = array ? new BasicArray() : new BasicDocument();
// Read the elements ...
while (data.getTotalBytesRead() < endingIndex) {
byte type = data.readByte();
if (type == Bson.END_OF_DOCUMENT) break;
readElement(type, doc);
}
return doc;
}
protected void readElement( byte type,
MutableDocument bson ) throws IOException {
String name = readCString();
Object value = null;
switch (type) {
case Bson.Type.ARRAY:
value = readDocument(true);
break;
case Bson.Type.BINARY:
int length = data.readInt();
byte subtype = data.readByte();
if (subtype == BinaryType.UUID) {
long mostSig = data.readLong();
long leastSig = data.readLong();
value = new UUID(mostSig, leastSig);
} else {
byte[] bytes = new byte[length];
data.readFully(bytes);
value = values.createBinary(subtype, bytes);
}
break;
case Bson.Type.BOOLEAN:
value = values.createBoolean(data.readBoolean());
break;
case Bson.Type.DATETIME:
value = values.createDate(data.readLong());
break;
case Bson.Type.DBPOINTER:
// Deprecated, so ignore ...
break;
case Bson.Type.DOCUMENT:
value = readDocument(false);
break;
case Bson.Type.DOUBLE:
value = values.createDouble(data.readDouble());
break;
case Bson.Type.INT32:
value = values.createInt(data.readInt());
break;
case Bson.Type.INT64:
value = values.createLong(data.readLong());
break;
case Bson.Type.JAVASCRIPT:
value = values.createCode(readString());
break;
case Bson.Type.JAVASCRIPT_WITH_SCOPE:
data.readInt(); // the length, but we don't use this
String code = readString();
Document scope = readDocument(false);
value = values.createCode(code, scope);
break;
case Bson.Type.MAXKEY:
value = MaxKey.getInstance();
break;
case Bson.Type.MINKEY:
value = MinKey.getInstance();
break;
case Bson.Type.NULL:
value = values.createNull();
break;
case Bson.Type.OBJECTID:
byte[] objectIdBytes = new byte[12];
data.readFully(objectIdBytes);
value = values.createObjectId(objectIdBytes);
break;
case Bson.Type.REGEX:
value = values.createRegex(readCString(), readCString());
break;
case Bson.Type.STRING:
value = readString();
break;
case Bson.Type.SYMBOL:
value = readString();
break;
case Bson.Type.TIMESTAMP:
int inc = data.readInt();
int time = data.readInt();
value = values.createTimestamp(time, inc);
break;
case Bson.Type.UNDEFINED:
// ignore ...
break;
}
bson.put(name, value);
}
protected String readCString() throws IOException {
return data.readUTF(-1); // this reads the zero-byte terminator
}
protected String readString() throws IOException {
int length = data.readInt();
String result = values.createString(data.readUTF(length - 1)); // don't read the zero-byte
data.readByte(); // reads the zero-byte terminator
return result;
}
protected Document endDocument() {
return object;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy