Skip to content

Commit a99037f

Browse files
committed
Fix #155 (manually backport)
1 parent 82b282d commit a99037f

File tree

23 files changed

+416
-26
lines changed

23 files changed

+416
-26
lines changed

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/AvroGenerator.java

+3-2
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,11 @@ public final void writeStringField(String fieldName, String value)
305305

306306
@Override
307307
public final void flush() throws IOException {
308-
_output.flush();
308+
if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
309+
_output.flush();
310+
}
309311
}
310312

311-
@SuppressWarnings("deprecation")
312313
@Override
313314
public void close() throws IOException
314315
{

cbor/src/main/java/com/fasterxml/jackson/dataformat/cbor/CBORGenerator.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1097,7 +1097,6 @@ private void _failSizedArrayOrObject() throws IOException
10971097
/**********************************************************
10981098
*/
10991099

1100-
@SuppressWarnings("deprecation")
11011100
@Override
11021101
public final void flush() throws IOException {
11031102
_flushBuffer();
@@ -1129,7 +1128,8 @@ && isEnabled(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT)) {
11291128
if (_ioContext.isResourceManaged()
11301129
|| isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET)) {
11311130
_out.close();
1132-
} else {
1131+
} else if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
1132+
// 14-Jan-2019, tatu: [dataformats-binary#155]: unless prevented via feature
11331133
// If we can't close it, we should at least flush
11341134
_out.flush();
11351135
}

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/CBORTestBase.java

+1-2
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,7 @@ protected CBORMapper cborMapper() {
4646
}
4747

4848
protected CBORFactory cborFactory() {
49-
CBORFactory f = new CBORFactory();
50-
return f;
49+
return new CBORFactory();
5150
}
5251

5352
protected byte[] cborDoc(String json) throws IOException {

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/filter/StreamingDecoratorsTest.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
import com.fasterxml.jackson.core.*;
66
import com.fasterxml.jackson.dataformat.cbor.*;
7-
import com.fasterxml.jackson.dataformat.cbor.util.PrefixInputDecorator;
8-
import com.fasterxml.jackson.dataformat.cbor.util.PrefixOutputDecorator;
7+
import com.fasterxml.jackson.dataformat.cbor.testutil.PrefixInputDecorator;
8+
import com.fasterxml.jackson.dataformat.cbor.testutil.PrefixOutputDecorator;
99

1010
public class StreamingDecoratorsTest extends CBORTestBase
1111
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
package com.fasterxml.jackson.dataformat.cbor.gen;
2+
3+
import com.fasterxml.jackson.core.*;
4+
import com.fasterxml.jackson.dataformat.cbor.CBORTestBase;
5+
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
6+
import com.fasterxml.jackson.dataformat.cbor.testutil.ByteOutputStreamForTesting;
7+
8+
/**
9+
* Set of basic unit tests that verify aspect of closing a
10+
* {@link JsonGenerator} instance. This includes both closing
11+
* of physical resources (target), and logical content
12+
* (json content tree)
13+
*<p>
14+
* Specifically, features
15+
* <code>JsonGenerator.Feature#AUTO_CLOSE_TARGET</code>
16+
* and
17+
* <code>JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT</code>
18+
* are tested.
19+
*/
20+
public class TestGeneratorClosing extends CBORTestBase
21+
{
22+
/*
23+
/**********************************************************
24+
/* Unit tests
25+
/**********************************************************
26+
*/
27+
28+
/**
29+
* This unit test checks the default behaviour; with no auto-close, no
30+
* automatic closing should occur, nor explicit one unless specific
31+
* forcing method is used.
32+
*/
33+
public void testNoAutoCloseGenerator() throws Exception
34+
{
35+
JsonFactory f = cborFactory();
36+
37+
// Check the default settings
38+
assertTrue(f.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET));
39+
// then change
40+
f.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
41+
assertFalse(f.isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET));
42+
43+
try (final ByteOutputStreamForTesting output = new ByteOutputStreamForTesting()) {
44+
JsonGenerator g = f.createGenerator(output);
45+
46+
// shouldn't be closed to begin with...
47+
assertFalse(output.isClosed());
48+
g.writeNumber(39);
49+
// regular close won't close it either:
50+
g.close();
51+
assertFalse(output.isClosed());
52+
}
53+
}
54+
55+
public void testCloseGenerator() throws Exception
56+
{
57+
JsonFactory f = cborFactory();
58+
f.enable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
59+
@SuppressWarnings("resource")
60+
ByteOutputStreamForTesting output = new ByteOutputStreamForTesting();
61+
JsonGenerator g = f.createGenerator(output);
62+
63+
// shouldn't be closed to begin with...
64+
assertFalse(output.isClosed());
65+
g.writeNumber(39);
66+
// but close() should now close the writer
67+
g.close();
68+
assertTrue(output.isClosed());
69+
}
70+
71+
public void testNoAutoCloseOutputStream() throws Exception
72+
{
73+
JsonFactory f = cborFactory();
74+
f.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
75+
@SuppressWarnings("resource")
76+
ByteOutputStreamForTesting output = new ByteOutputStreamForTesting();
77+
JsonGenerator g = f.createGenerator(output, JsonEncoding.UTF8);
78+
79+
assertFalse(output.isClosed());
80+
g.writeNumber(39);
81+
g.close();
82+
assertFalse(output.isClosed());
83+
}
84+
85+
@SuppressWarnings("resource")
86+
public void testAutoFlushOrNot() throws Exception
87+
{
88+
JsonFactory f = cborFactory();
89+
90+
ByteOutputStreamForTesting bytes = new ByteOutputStreamForTesting();
91+
JsonGenerator g = f.createGenerator(bytes, JsonEncoding.UTF8);
92+
g.writeStartArray();
93+
g.writeEndArray();
94+
assertEquals(0, bytes.flushCount);
95+
g.flush();
96+
assertEquals(1, bytes.flushCount);
97+
final int EXP_LENGTH = 2;
98+
assertEquals(EXP_LENGTH, bytes.toByteArray().length);
99+
g.close();
100+
101+
// then disable and we should not see flushing again...
102+
f = newFactoryBuilder()
103+
.disable(StreamWriteFeature.FLUSH_PASSED_TO_STREAM)
104+
// also need to disable this, to prevent implicit flush() on close()
105+
.disable(StreamWriteFeature.AUTO_CLOSE_TARGET)
106+
.build();
107+
108+
// and then with OutputStream
109+
bytes = new ByteOutputStreamForTesting();
110+
g = f.createGenerator(bytes, JsonEncoding.UTF8);
111+
g.writeStartArray();
112+
g.writeEndArray();
113+
assertEquals(0, bytes.flushCount);
114+
g.flush();
115+
assertEquals(0, bytes.flushCount);
116+
// and, as long as we won't be auto-closing, still no flush
117+
g.close();
118+
assertEquals(0, bytes.flushCount);
119+
// and only direct `close()` will do it
120+
bytes.close();
121+
assertEquals(EXP_LENGTH, bytes.toByteArray().length);
122+
}
123+
124+
private TSFBuilder<?, ?> newFactoryBuilder() {
125+
return CBORFactory.builder();
126+
}
127+
}

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/mapper/BinaryReadTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import com.fasterxml.jackson.core.JsonToken;
1010
import com.fasterxml.jackson.databind.ObjectMapper;
1111
import com.fasterxml.jackson.dataformat.cbor.CBORTestBase;
12-
import com.fasterxml.jackson.dataformat.cbor.util.ThrottledInputStream;
12+
import com.fasterxml.jackson.dataformat.cbor.testutil.ThrottledInputStream;
1313

1414
public class BinaryReadTest extends CBORTestBase
1515
{

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/BasicParserTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
88
import com.fasterxml.jackson.dataformat.cbor.CBORParser;
99
import com.fasterxml.jackson.dataformat.cbor.CBORTestBase;
10-
import com.fasterxml.jackson.dataformat.cbor.util.ThrottledInputStream;
10+
import com.fasterxml.jackson.dataformat.cbor.testutil.ThrottledInputStream;
1111

1212
/**
1313
* Unit tests for simple value types.

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/ParserNextXxxTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import com.fasterxml.jackson.core.io.SerializedString;
88
import com.fasterxml.jackson.dataformat.cbor.CBORFactory;
99
import com.fasterxml.jackson.dataformat.cbor.CBORTestBase;
10-
import com.fasterxml.jackson.dataformat.cbor.util.ThrottledInputStream;
10+
import com.fasterxml.jackson.dataformat.cbor.testutil.ThrottledInputStream;
1111

1212
// note: copied from test of same name from jackson-dataformat-smile
1313
public class ParserNextXxxTest extends CBORTestBase

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/ParserNumbersTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import com.fasterxml.jackson.dataformat.cbor.CBORGenerator;
1616
import com.fasterxml.jackson.dataformat.cbor.CBORParser;
1717
import com.fasterxml.jackson.dataformat.cbor.CBORTestBase;
18-
import com.fasterxml.jackson.dataformat.cbor.util.ThrottledInputStream;
18+
import com.fasterxml.jackson.dataformat.cbor.testutil.ThrottledInputStream;
1919

2020
@SuppressWarnings("resource")
2121
public class ParserNumbersTest extends CBORTestBase

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/parse/UnicodeHandlingTest.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import com.fasterxml.jackson.core.JsonToken;
66
import com.fasterxml.jackson.dataformat.cbor.*;
7-
import com.fasterxml.jackson.dataformat.cbor.util.ThrottledInputStream;
7+
import com.fasterxml.jackson.dataformat.cbor.testutil.ThrottledInputStream;
88

99
public class UnicodeHandlingTest extends CBORTestBase
1010
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
package com.fasterxml.jackson.dataformat.cbor.testutil;
2+
3+
import java.io.ByteArrayOutputStream;
4+
import java.io.IOException;
5+
6+
/**
7+
* Helper class for verifying that {@link java.io.OutputStream} is (or is not)
8+
* closed and/or flushed.
9+
*/
10+
public class ByteOutputStreamForTesting extends ByteArrayOutputStream
11+
{
12+
public int closeCount = 0;
13+
public int flushCount = 0;
14+
15+
public ByteOutputStreamForTesting() { }
16+
17+
@Override
18+
public void close() throws IOException {
19+
++closeCount;
20+
super.close();
21+
}
22+
23+
@Override
24+
public void flush() throws IOException
25+
{
26+
++flushCount;
27+
super.flush();
28+
}
29+
30+
public boolean isClosed() { return closeCount > 0; }
31+
public boolean isFlushed() { return flushCount > 0; }
32+
}

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/util/PrefixInputDecorator.java renamed to cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/testutil/PrefixInputDecorator.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.fasterxml.jackson.dataformat.cbor.util;
1+
package com.fasterxml.jackson.dataformat.cbor.testutil;
22

33
import java.io.ByteArrayInputStream;
44
import java.io.IOException;

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/util/PrefixOutputDecorator.java renamed to cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/testutil/PrefixOutputDecorator.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.fasterxml.jackson.dataformat.cbor.util;
1+
package com.fasterxml.jackson.dataformat.cbor.testutil;
22

33
import java.io.FilterOutputStream;
44
import java.io.IOException;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
package com.fasterxml.jackson.dataformat.cbor.testutil;
2+
3+
import java.io.IOException;
4+
import java.io.StringWriter;
5+
6+
public class StringWriterForTesting extends StringWriter
7+
{
8+
public int closeCount = 0;
9+
public int flushCount = 0;
10+
11+
public StringWriterForTesting() { }
12+
13+
@Override
14+
public void close() throws IOException {
15+
++closeCount;
16+
super.close();
17+
}
18+
19+
@Override
20+
public void flush()
21+
{
22+
++flushCount;
23+
super.flush();
24+
}
25+
26+
public boolean isClosed() { return closeCount > 0; }
27+
public boolean isFlushed() { return flushCount > 0; }
28+
}

cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/util/ThrottledInputStream.java renamed to cbor/src/test/java/com/fasterxml/jackson/dataformat/cbor/testutil/ThrottledInputStream.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.fasterxml.jackson.dataformat.cbor.util;
1+
package com.fasterxml.jackson.dataformat.cbor.testutil;
22

33
import java.io.*;
44

ion/src/main/java/com/fasterxml/jackson/dataformat/ion/IonGenerator.java

+9-5
Original file line numberDiff line numberDiff line change
@@ -100,8 +100,10 @@ public void close() throws IOException
100100
if (_ioContext.isResourceManaged()) {
101101
_destination.close();
102102
} else {
103-
if (_destination instanceof Flushable) {
104-
((Flushable) _destination).flush();
103+
if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
104+
if (_destination instanceof Flushable) {
105+
((Flushable) _destination).flush();
106+
}
105107
}
106108
}
107109
}
@@ -110,9 +112,11 @@ public void close() throws IOException
110112
@Override
111113
public void flush() throws IOException
112114
{
113-
Object dst = _ioContext.getSourceReference();
114-
if (dst instanceof Flushable) {
115-
((Flushable) dst).flush();
115+
if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
116+
Object dst = _ioContext.getSourceReference();
117+
if (dst instanceof Flushable) {
118+
((Flushable) dst).flush();
119+
}
116120
}
117121
}
118122

protobuf/src/main/java/com/fasterxml/jackson/dataformat/protobuf/ProtobufGenerator.java

+5-3
Original file line numberDiff line numberDiff line change
@@ -324,10 +324,11 @@ public final void flush() throws IOException
324324
_output.write(_currBuffer, start, len);
325325
}
326326
}
327-
_output.flush();
327+
if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
328+
_output.flush();
329+
}
328330
}
329331

330-
@SuppressWarnings("deprecation")
331332
@Override
332333
public void close() throws IOException
333334
{
@@ -351,7 +352,8 @@ public void close() throws IOException
351352
if (_output != null) {
352353
if (_ioContext.isResourceManaged() || isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET)) {
353354
_output.close();
354-
} else if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
355+
} else if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
356+
// 14-Jan-2019, tatu: [dataformats-binary#155]: unless prevented via feature
355357
// If we can't close it, we should at least flush
356358
_output.flush();
357359
}

release-notes/CREDITS-2.x

+4
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,7 @@ Michael Milkin (mmilkin@github)
7777
Guido Medina (guidomedina@github)
7878
* Reported #153: (smile) Unable to set a compression input/output decorator to a `SmileFactory`
7979
(2.9.8)
80+
81+
Carter Kozak (cakofony@github)
82+
* Reported, suggested fix for #155: Inconsistent support for FLUSH_PASSED_TO_STREAM
83+
(2.10.0)

release-notes/VERSION-2.x

+2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Project: jackson-datatypes-binaryModules:
1212

1313
#139: Incorrect decimal fraction representation
1414
(reported by wlukowicz@github)
15+
#155: Inconsistent support for FLUSH_PASSED_TO_STREAM
16+
(reported, fix suggested by Carter K)
1517

1618
2.9.8 (15-Dec-2018)
1719

smile/src/main/java/com/fasterxml/jackson/dataformat/smile/SmileGenerator.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -1770,7 +1770,6 @@ protected final void _verifyValueWrite(String typeMsg)
17701770
/**********************************************************
17711771
*/
17721772

1773-
@SuppressWarnings("deprecation")
17741773
@Override
17751774
public final void flush() throws IOException
17761775
{
@@ -1807,8 +1806,9 @@ && isEnabled(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT)) {
18071806

18081807
if (_ioContext.isResourceManaged() || isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET)) {
18091808
_out.close();
1810-
} else {
1809+
} else if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
18111810
// If we can't close it, we should at least flush
1811+
// 14-Jan-2019, tatu: [dataformats-binary#155]: unless prevented via feature
18121812
_out.flush();
18131813
}
18141814
// Internal buffer(s) generator has can now be released as well

0 commit comments

Comments
 (0)