/** * Throws an InvalidOperationException when the method called is not valid for the current state. * * @param methodName The name of the method. * @param validStates The valid states. * @throws BSONException */ protected void throwInvalidState(final String methodName, final State... validStates) { final String message; if (state == State.INITIAL || state == State.SCOPE_DOCUMENT || state == State.DONE) { if (!methodName.startsWith("end") && !methodName.equals("writeName")) { // NOPMD //NOPMD collapsing these if statements will not aid readability String typeName = methodName.substring(5); if (typeName.startsWith("start")) { typeName = typeName.substring(5); } String article = "A"; if (Arrays.asList('A', 'E', 'I', 'O', 'U').contains(typeName.charAt(0))) { article = "An"; } message = format("%s %s value cannot be written to the root level of a BSON document.", article, typeName); throw new BSONException(message); } } final String validStatesString = StringUtils.join(" or ", Arrays.asList(validStates)); message = format("%s can only be called when State is %s, not when State is %s", methodName, validStatesString, state); throw new BSONException(message); }
protected <V> void encodeObject(final BsonWriter writer, V value, final EncoderContext ctx, Class<V> objType) { Codec<V> codec = reg.get(objType); if (codec == null) { throw new BSONException("No codec for class " + objType); } codec.encode(writer, value, ctx); }
protected <V> V decodeObject(final BsonReader reader, final DecoderContext ctx, Class<V> objType) { Codec<V> codec = reg.get(objType); if (codec == null) { throw new BSONException("No codec for class " + objType); } return codec.decode(reader, ctx); }
protected <I> List<I> decodeGenericList(final BsonReader reader, final DecoderContext ctx, Class<I> itemType) { Codec<I> codec = reg.get(itemType); if (codec == null) { throw new BSONException("No codec for class " + itemType); } List<I> list = new ArrayList<>(); reader.readStartArray(); while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { list.add(codec.decode(reader, ctx)); } reader.readEndArray(); return list; }
protected <I> Set<I> decodeGenericSet(final BsonReader reader, final DecoderContext ctx, Class<I> itemType) { Codec<I> codec = reg.get(itemType); if (codec == null) { throw new BSONException("No codec for class " + itemType); } Set<I> set = new HashSet<>(); reader.readStartArray(); while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { set.add(codec.decode(reader, ctx)); } reader.readEndArray(); return set; }
protected <I> Map<String, I> decodeGenericStringMap(final BsonReader reader, final DecoderContext ctx, Class<I> itemType) { Codec<I> codec = reg.get(itemType); if (codec == null) { throw new BSONException("No codec for class " + itemType); } Map<String, I> map = new HashMap<>(); reader.readStartDocument(); while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { map.put(reader.readName(), codec.decode(reader, ctx)); } reader.readEndDocument(); return map; }
protected <I> Map<Long, I> decodeGenericLongMap(final BsonReader reader, final DecoderContext ctx, Class<I> itemType) { Codec<I> codec = reg.get(itemType); if (codec == null) { throw new BSONException("No codec for class " + itemType); } Map<Long, I> map = new HashMap<>(); reader.readStartArray(); while (reader.readBsonType() != BsonType.END_OF_DOCUMENT) { map.put(reader.readInt64(), codec.decode(reader, ctx)); } reader.readEndArray(); return map; }
@Test public void testUnkownFail() { MongoDatabase db = connect(); UnknownFailPojo pojo = new UnknownFailPojo(); pojo.setName("john"); MongoCollection<UnknownFailPojo> coll = db.getCollection(COLL_NAME, UnknownFailPojo.class); coll.insertOne(pojo); db.getCollection(COLL_NAME).updateOne(Filters.eq("_id", pojo.getId()), Updates.set("anotherNewField", "theNewValue")); try { @SuppressWarnings("unused") UnknownFailPojo readPojo = coll.find().first(); } catch (BSONException e) { assertThat(e.getMessage()).isEqualTo( "ch.rasc.bsoncodec.test.unknown.UnknownFailPojoCodec does not contain a matching property for the field 'anotherNewField'"); } Document doc = db.getCollection(COLL_NAME).find().first(); assertThat(doc).hasSize(3); assertThat(doc.get("_id")).isEqualTo(pojo.getId()); assertThat(doc.get("name")).isEqualTo("john"); assertThat(doc.get("anotherNewField")).isEqualTo("theNewValue"); }
public String getUTF8String(int valueOffset) { int size = getInt(valueOffset) - 1; try { return new String(array(), valueOffset + 4, size, "UTF-8"); } catch (UnsupportedEncodingException e) { throw new BSONException( "Cannot decode string as UTF-8." ); } }
private int writeCString(final String str, final boolean checkForNullCharacters) { final int len = str.length(); int total = 0; for (int i = 0; i < len;/*i gets incremented*/) { final int c = Character.codePointAt(str, i); if (checkForNullCharacters && c == 0x0) { throw new BSONException( String.format("BSON cstring '%s' is not valid because it contains a null character at index %d", str, i)); } if (c < 0x80) { write((byte) c); total += 1; } else if (c < 0x800) { write((byte) (0xc0 + (c >> 6))); write((byte) (0x80 + (c & 0x3f))); total += 2; } else if (c < 0x10000) { write((byte) (0xe0 + (c >> 12))); write((byte) (0x80 + ((c >> 6) & 0x3f))); write((byte) (0x80 + (c & 0x3f))); total += 3; } else { write((byte) (0xf0 + (c >> 18))); write((byte) (0x80 + ((c >> 12) & 0x3f))); write((byte) (0x80 + ((c >> 6) & 0x3f))); write((byte) (0x80 + (c & 0x3f))); total += 4; } i += Character.charCount(c); } write((byte) 0); total++; return total; }
/** * Writes the start of a BSON array to the writer. * * @throws BSONException if maximum serialization depth exceeded. */ public void writeStartArray() { serializationDepth++; if (serializationDepth > settings.getMaxSerializationDepth()) { throw new BSONException("Maximum serialization depth exceeded (does the object being serialized have a circular reference?)."); } }
/** * Writes the start of a BSON document to the writer. * * @throws BSONException if maximum serialization depth exceeded. */ public void writeStartDocument() { serializationDepth++; if (serializationDepth > settings.getMaxSerializationDepth()) { throw new BSONException("Maximum serialization depth exceeded (does the object being serialized have a circular reference?)."); } }
/** * Throws an InvalidOperationException when the method called is not valid for the current ContextType. * * @param methodName The name of the method. * @param actualContextType The actual ContextType. * @param validContextTypes The valid ContextTypes. * @throws BSONException */ protected void throwInvalidContextType(final String methodName, final BSONContextType actualContextType, final BSONContextType... validContextTypes) { final String validContextTypesString = StringUtils.join(" or ", Arrays.asList(validContextTypes)); final String message = format("%s can only be called when ContextType is %s, " + "not when ContextType is %s.", methodName, validContextTypesString, actualContextType); throw new BSONException(message); }
private void addDecodeMethod(Builder classBuilder, List<FieldModel> fieldModel) { MethodSpec.Builder decode = MethodSpec.methodBuilder("decode") .returns(this.thisType).addModifiers(Modifier.PUBLIC) .addAnnotation(Override.class).addParameter(BsonReader.class, "reader") .addParameter(DecoderContext.class, "decoderContext") .addStatement("$T value = new $T()", this.thisType, this.thisType) .addStatement("reader.readStartDocument()") .addStatement("$T bsonType", BsonType.class) .beginControlFlow( "while ((bsonType = reader.readBsonType()) != $T.END_OF_DOCUMENT)", BsonType.class) .addStatement("String name = reader.readName()"); boolean allDisableSetNullStatement = fieldModel.stream() .allMatch(FieldModel::disableSetNullStatement); boolean someDecodeNullCheck = fieldModel.stream() .filter(f -> !f.disableDecodeNullCheck()).findAny().isPresent(); boolean handleNull = allDisableSetNullStatement && someDecodeNullCheck; if (handleNull) { decode.beginControlFlow("if (bsonType != $T.NULL)", BsonType.class); } decode.beginControlFlow("switch (name)"); for (FieldModel field : fieldModel) { decode.beginControlFlow("case $S:", field.name()); String getter = "value." + field.methodNameGet() + "()"; String setter = "value." + field.methodNameSet() + "(%s)"; CodeGeneratorContext ctx = new CodeGeneratorContext(ImmutableFieldModel .copyOf(field).withDisableDecodeNullCheck(handleNull), decode, this.instanceFields, getter, setter); field.codeGen().addDecodeStatements(ctx); decode.addStatement("break"); decode.endControlFlow(); } if (this.ignoreUnknown) { decode.addStatement("default:\nreader.skipValue()").endControlFlow(); } else { decode.addStatement( "default:\nthrow new $T(this.getClass().getName() + $S + name + $S)", BSONException.class, " does not contain a matching property for the field '", "'") .endControlFlow(); } if (handleNull) { decode.nextControlFlow("else").addStatement("reader.readNull()"); decode.endControlFlow(); } decode.endControlFlow().addStatement("reader.readEndDocument()") .addStatement("return value"); classBuilder.addMethod(decode.build()); }