Skip to content

Commit 2e2836e

Browse files
committed
Ensure IonReader instances created within IonFactory are always resource-managed.
1 parent d72e4f2 commit 2e2836e

File tree

2 files changed

+90
-3
lines changed

2 files changed

+90
-3
lines changed

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

+8-3
Original file line numberDiff line numberDiff line change
@@ -360,14 +360,17 @@ protected JsonParser _createParser(InputStream in, IOContext ctxt)
360360
throws IOException
361361
{
362362
IonReader ion = _system.newReader(in);
363-
return new IonParser(ion, _system, ctxt, getCodec(), _ionParserFeatures);
363+
return new IonParser(ion, _system,
364+
_createContext(_createContentReference(ion), true), getCodec(), _ionParserFeatures);
364365
}
365366

366367
@Override
367368
protected JsonParser _createParser(Reader r, IOContext ctxt)
368369
throws IOException
369370
{
370-
return new IonParser(_system.newReader(r), _system, ctxt, getCodec(), _ionParserFeatures);
371+
IonReader ion = _system.newReader(r);
372+
return new IonParser(ion, _system,
373+
_createContext(_createContentReference(ion), true), getCodec(), _ionParserFeatures);
371374
}
372375

373376
@Override
@@ -381,7 +384,9 @@ protected JsonParser _createParser(char[] data, int offset, int len, IOContext c
381384
protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt)
382385
throws IOException
383386
{
384-
return new IonParser(_system.newReader(data, offset, len), _system, ctxt, getCodec(), _ionParserFeatures);
387+
IonReader ion = _system.newReader(data, offset, len);
388+
return new IonParser(ion, _system,
389+
_createContext(_createContentReference(ion), true), getCodec(), _ionParserFeatures);
385390
}
386391

387392
@Override
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package com.fasterxml.jackson.dataformat.ion;
2+
3+
import com.amazon.ion.IonReader;
4+
import org.junit.Test;
5+
import org.junit.runner.RunWith;
6+
import org.junit.runners.Parameterized;
7+
8+
import java.io.ByteArrayInputStream;
9+
import java.io.IOException;
10+
import java.io.StringReader;
11+
12+
import static org.junit.Assert.assertEquals;
13+
import static org.junit.Assert.assertTrue;
14+
15+
@RunWith(Parameterized.class)
16+
public class IonFactoryTest {
17+
18+
// 4-byte Ion 1.0 IVM followed by int 0.
19+
private static final byte[] BINARY_INT_0 = new byte[] {(byte) 0xE0, 0x01, 0x00, (byte) 0xEA, 0x20};
20+
private static final String TEXT_INT_0 = "0";
21+
22+
private enum InputSource {
23+
BYTE_ARRAY() {
24+
@Override
25+
IonParser newParser(IonFactory factory) throws IOException {
26+
return (IonParser) factory.createParser(BINARY_INT_0);
27+
}
28+
},
29+
CHAR_ARRAY() {
30+
@Override
31+
IonParser newParser(IonFactory factory) throws IOException {
32+
return (IonParser) factory.createParser(TEXT_INT_0.toCharArray());
33+
}
34+
},
35+
READER() {
36+
@Override
37+
IonParser newParser(IonFactory factory) throws IOException {
38+
return (IonParser) factory.createParser(new StringReader(TEXT_INT_0));
39+
}
40+
},
41+
INPUT_STREAM() {
42+
@Override
43+
IonParser newParser(IonFactory factory) throws IOException {
44+
return (IonParser) factory.createParser(new ByteArrayInputStream(BINARY_INT_0));
45+
}
46+
},
47+
ION_READER() {
48+
@Override
49+
IonParser newParser(IonFactory factory) {
50+
return factory.createParser(factory.getIonSystem().newReader(BINARY_INT_0));
51+
}
52+
},
53+
ION_VALUE() {
54+
@Override
55+
IonParser newParser(IonFactory factory) {
56+
return factory.createParser(factory.getIonSystem().newInt(0));
57+
}
58+
};
59+
60+
abstract IonParser newParser(IonFactory factory) throws IOException;
61+
}
62+
63+
@Parameterized.Parameters(name = "{0}")
64+
public static InputSource[] parameters() {
65+
return InputSource.values();
66+
}
67+
68+
@Parameterized.Parameter
69+
public InputSource inputSource;
70+
71+
@Test
72+
public void testIonParserIsResourceManaged() throws IOException {
73+
IonFactory factory = new IonFactory();
74+
IonParser parser = inputSource.newParser(factory);
75+
// When the user provides an IonReader, it is not resource-managed, meaning that the user retains the
76+
// responsibility to close it. In all other cases, the IonReader is created internally, is resource-managed,
77+
// and is closed automatically in IonParser.close().
78+
assertEquals(inputSource != InputSource.ION_READER, parser._ioContext.isResourceManaged());
79+
assertTrue(IonReader.class.isAssignableFrom(parser._ioContext.contentReference().getRawContent().getClass()));
80+
parser.close();
81+
}
82+
}

0 commit comments

Comments
 (0)