Skip to content

Commit

Permalink
Merge branch 'FasterXML:2.16' into 2.16
Browse files Browse the repository at this point in the history
  • Loading branch information
djay-S authored Aug 2, 2023
2 parents 09a913a + 82feede commit add42ed
Show file tree
Hide file tree
Showing 22 changed files with 268 additions and 53 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,13 @@ private Feature(boolean defaultState) {
EMPTY_SCHEMA = CsvSchema.emptySchema();
}

final protected IOContext _ioContext;
protected final IOContext _ioContext;

/**
* @since 2.16
*/
protected final StreamWriteConstraints _streamWriteConstraints;

/**
* Bit flag composed of bits that indicate which
* {@link CsvGenerator.Feature}s
Expand Down Expand Up @@ -243,6 +248,7 @@ public CsvGenerator(IOContext ctxt, int jsonFeatures, int csvFeatures,
{
super(jsonFeatures, codec);
_ioContext = ctxt;
_streamWriteConstraints = ctxt.streamWriteConstraints();
_formatFeatures = csvFeatures;
_schema = schema;
boolean useFastDoubleWriter = isEnabled(StreamWriteFeature.USE_FAST_DOUBLE_WRITER);
Expand All @@ -257,6 +263,7 @@ public CsvGenerator(IOContext ctxt, int jsonFeatures, int csvFeatures,
{
super(jsonFeatures, codec);
_ioContext = ctxt;
_streamWriteConstraints = ctxt.streamWriteConstraints();
_formatFeatures = csvFeatures;
_writer = csvWriter;
_writeContext = null; // just to make sure it won't be used
Expand Down Expand Up @@ -478,6 +485,11 @@ public CsvGenerator disable(Feature f) {
return this;
}

@Override
public StreamWriteConstraints streamWriteConstraints() {
return _streamWriteConstraints;
}

/*
/**********************************************************
/* Public API: low-level I/O
Expand Down Expand Up @@ -551,6 +563,7 @@ && _skipValue && isEnabled(JsonGenerator.Feature.IGNORE_UNKNOWN)) {
}
}
_tokenWriteContext = _tokenWriteContext.createChildArrayContext(null);
streamWriteConstraints().validateNestingDepth(_tokenWriteContext.getNestingDepth());
// and that's about it, really
}

Expand Down Expand Up @@ -597,6 +610,7 @@ public final void writeStartObject() throws IOException
}
}
_tokenWriteContext = _tokenWriteContext.createChildObjectContext(null);
streamWriteConstraints().validateNestingDepth(_tokenWriteContext.getNestingDepth());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -279,14 +279,6 @@ public Column(int index, String name, ColumnType type) {
this(index, name, type, "");
}

/**
* @deprecated use variant where `arrayElementSep` is <code>String</code>
*/
@Deprecated // in 2.7; remove from 2.8
public Column(int index, String name, ColumnType type, int arrayElementSep) {
this(index, name, type, (arrayElementSep < 0) ? NO_ARRAY_ELEMENT_SEPARATOR : Character.toString((char) arrayElementSep));
}

public Column(int index, String name, ColumnType type, String arrayElementSep)
{
_index = index;
Expand Down Expand Up @@ -529,15 +521,6 @@ public Builder addArrayColumn(String name) {
return addColumn(new Column(index, name, ColumnType.ARRAY, ""));
}

/**
* @deprecated use {@link #addArrayColumn(String, String)} instead
*/
@Deprecated // in 2.7; remove from 2.8
public Builder addArrayColumn(String name, int elementSeparator) {
int index = _columns.size();
return addColumn(new Column(index, name, ColumnType.ARRAY, elementSeparator));
}

/**
* @since 2.7
*/
Expand All @@ -554,15 +537,24 @@ public Builder addBooleanColumn(String name) {
return addColumn(new Column(index, name, ColumnType.BOOLEAN));
}

public Builder renameColumn(int index, String newName) {
_checkIndex(index);
_columns.set(index, _columns.get(index).withName(newName));
return this;
}

public Builder replaceColumn(int index, Column c) {
_checkIndex(index);
_columns.set(index, c);
return this;
}

public Builder renameColumn(int index, String newName) {
/**
* @since 2.16
*/
public Builder removeColumn(int index) {
_checkIndex(index);
_columns.set(index, _columns.get(index).withName(newName));
_columns.remove(index);
return this;
}

Expand Down Expand Up @@ -603,15 +595,6 @@ public Builder removeArrayElementSeparator(int index) {
return this;
}

/**
* @deprecated use {@link #setArrayElementSeparator(String)} instead
*/
@Deprecated // in 2.7; remove from 2.8
public void setArrayElementSeparator(int index, char sep) {
_checkIndex(index);
_columns.set(index, _columns.get(index).withElementSeparator(sep));
}

/**
* @since 2.7
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ protected SimpleTokenWriteContext(int type, SimpleTokenWriteContext parent, DupD
super();
_type = type;
_parent = parent;
_nestingDepth = parent == null ? 0 : parent._nestingDepth + 1;
_dups = dups;
_index = -1;
_currentValue = currentValue;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class CSVBigStringsTest extends ModuleTestBase
{
private final CsvMapper MAPPER = mapperForCsv();

private final static int TOO_LONG_STRING_VALUE_LEN = 20_000_100;

private CsvMapper newCsvMapperWithUnlimitedStringSizeSupport() {
CsvFactory csvFactory = CsvFactory.builder()
.streamReadConstraints(StreamReadConstraints.builder().maxStringLength(Integer.MAX_VALUE).build())
Expand All @@ -29,12 +31,13 @@ public void testBigString() throws Exception
MappingIterator<List<String>> it = MAPPER
.readerForListOf(String.class)
.with(CsvParser.Feature.WRAP_AS_ARRAY)
.readValues(generateCsv(5001000));
.readValues(generateCsv(TOO_LONG_STRING_VALUE_LEN));
it.readAll();
fail("expected DatabindException");
} catch (DatabindException e) {
assertTrue("unexpected exception message: " + e.getMessage(),
e.getMessage().startsWith("String value length (5001000) exceeds the maximum allowed"));
final String message = e.getMessage();
assertTrue("unexpected exception message: " + message, message.startsWith("String value length"));
assertTrue("unexpected exception message: " + message, message.contains("exceeds the maximum allowed ("));
}
}

Expand All @@ -44,21 +47,21 @@ public void testBiggerString() throws Exception
MappingIterator<List<String>> it = MAPPER
.readerForListOf(String.class)
.with(CsvParser.Feature.WRAP_AS_ARRAY)
.readValues(generateCsv(7_000_000));
.readValues(generateCsv(TOO_LONG_STRING_VALUE_LEN));
it.readAll();
fail("expected DatabindException");
} catch (DatabindException e) {
final String message = e.getMessage();
// this test fails when the TextBuffer is being resized, so we don't yet know just how big the string is
// so best not to assert that the String length value in the message is the full 2000000 value
// so best not to assert that the String length value in the message is the full 20_000_000 value
assertTrue("unexpected exception message: " + message, message.startsWith("String value length"));
assertTrue("unexpected exception message: " + message, message.contains("exceeds the maximum allowed"));
assertTrue("unexpected exception message: " + message, message.contains("exceeds the maximum allowed ("));
}
}

public void testUnlimitedString() throws Exception
{
final int len = 5001000;
final int len = TOO_LONG_STRING_VALUE_LEN;
MappingIterator<List<String>> it = newCsvMapperWithUnlimitedStringSizeSupport()
.readerForListOf(String.class)
.with(CsvParser.Feature.WRAP_AS_ARRAY)
Expand All @@ -77,4 +80,4 @@ private String generateCsv(final int len) {
}
return sb.toString();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ public void testUserWithTypedAutoSchema() throws Exception

// Then verify linkage
_verifyLinks(schema);

// and then modify it a bit
CsvSchema.Builder b = schema.rebuild();
b.removeColumn(1); // lastName;
assertEquals(4, b.build().size());
}

public void testArrayWithTypedAutoSchema() throws Exception
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.fasterxml.jackson.dataformat.csv.ser.dos;

import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.core.StreamWriteConstraints;

import com.fasterxml.jackson.databind.DatabindException;
import com.fasterxml.jackson.dataformat.csv.CsvMapper;
import com.fasterxml.jackson.dataformat.csv.ModuleTestBase;

/**
* Simple unit tests to verify that we fail gracefully if you attempt to serialize
* data that is cyclic (eg a list that contains itself).
*/
public class CyclicCSVDataSerTest extends ModuleTestBase
{
private final CsvMapper MAPPER = mapperForCsv();

public void testListWithSelfReference() throws Exception {
List<Object> list = new ArrayList<>();
list.add(list);
try {
MAPPER.writeValueAsString(list);
fail("expected DatabindException");
} catch (DatabindException e) {
String exceptionPrefix = String.format("Document nesting depth (%d) exceeds the maximum allowed",
StreamWriteConstraints.DEFAULT_MAX_DEPTH + 1);
assertTrue("DatabindException message is as expected?",
e.getMessage().startsWith(exceptionPrefix));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public abstract class JavaPropsGenerator extends GeneratorBase

protected final IOContext _ioContext;

/**
* @since 2.16
*/
protected final StreamWriteConstraints _streamWriteConstraints;

/**
* Definition of columns being written, if available.
*/
Expand Down Expand Up @@ -77,9 +82,15 @@ public JavaPropsGenerator(IOContext ctxt, int stdFeatures, ObjectCodec codec)
{
super(stdFeatures, codec, BOGUS_WRITE_CONTEXT);
_ioContext = ctxt;
_streamWriteConstraints = ctxt.streamWriteConstraints();
_jpropContext = JPropWriteContext.createRootContext();
}

@Override
public StreamWriteConstraints streamWriteConstraints() {
return _streamWriteConstraints;
}

@Override // since 2.13
public Object currentValue() {
return _jpropContext.getCurrentValue();
Expand Down Expand Up @@ -267,6 +278,7 @@ public void writeFieldName(String name) throws IOException
public void writeStartArray() throws IOException {
_verifyValueWrite("start an array");
_jpropContext = _jpropContext.createChildArrayContext(_basePath.length());
streamWriteConstraints().validateNestingDepth(_jpropContext.getNestingDepth());
}

@Override
Expand All @@ -281,6 +293,7 @@ public void writeEndArray() throws IOException {
public void writeStartObject() throws IOException {
_verifyValueWrite("start an object");
_jpropContext = _jpropContext.createChildObjectContext(_basePath.length());
streamWriteConstraints().validateNestingDepth(_jpropContext.getNestingDepth());
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ protected JPropWriteContext(int type, JPropWriteContext parent,
super();
_type = type;
_parent = parent;
_nestingDepth = parent == null ? 0 : parent._nestingDepth + 1;
_basePathLength = basePathLength;
_index = -1;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.fasterxml.jackson.dataformat.javaprop.dos;

import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.core.StreamWriteConstraints;

import com.fasterxml.jackson.databind.DatabindException;
import com.fasterxml.jackson.dataformat.javaprop.JavaPropsMapper;
import com.fasterxml.jackson.dataformat.javaprop.ModuleTestBase;

/**
* Simple unit tests to verify that we fail gracefully if you attempt to serialize
* data that is cyclic (eg a list that contains itself).
*/
public class CyclicPropsDataSerTest extends ModuleTestBase
{
private final JavaPropsMapper MAPPER = newPropertiesMapper();

public void testListWithSelfReference() throws Exception {
List<Object> list = new ArrayList<>();
list.add(list);
try {
MAPPER.writeValueAsString(list);
fail("expected DatabindException");
} catch (DatabindException e) {
String exceptionPrefix = String.format("Document nesting depth (%d) exceeds the maximum allowed",
StreamWriteConstraints.DEFAULT_MAX_DEPTH + 1);
assertTrue("JsonMappingException message is as expected?",
e.getMessage().startsWith(exceptionPrefix));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,10 @@ public void testDeeplyNestedData() throws IOException {
}
fail("expected StreamConstraintsException");
} catch (StreamConstraintsException e) {
String exceptionPrefix = String.format("Document nesting depth (%d) exceeds the maximum allowed",
StreamReadConstraints.DEFAULT_MAX_DEPTH + 1);
assertTrue("unexpected exception message: " + e.getMessage(),
e.getMessage().startsWith("Document nesting depth (1001) exceeds the maximum allowed"));
e.getMessage().startsWith(exceptionPrefix));
}
}

Expand Down
10 changes: 9 additions & 1 deletion release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,15 @@ Active Maintainers:
=== Releases ===
------------------------------------------------------------------------

2.15.1 (not yet released)
2.16.0 (not yet released)

#422: (csv) Add `removeColumn()` method in `CsvSchema.Builder`

2.15.2 (30-May-2023)

No changes since 2.15.1

2.15.1 (16-May-2023)

#404: (yaml) Cannot serialize YAML with Deduction-Based Polymorphism
(reported by Peter H)
Expand Down
Loading

0 comments on commit add42ed

Please sign in to comment.