Skip to content

Commit 893e7ff

Browse files
Add documentation for IonReader.close() method (#1081)
Fixes #1059: Make IonReader extend AutoCloseable for proper resource management This change enhances the IonReader interface with comprehensive documentation for the close() method to clarify resource management behavior and enable proper try-with-resources usage. The interface already extended Closeable (which extends AutoCloseable), but lacked explicit documentation about the close() method contract.
1 parent f732e97 commit 893e7ff

File tree

2 files changed

+156
-1
lines changed

2 files changed

+156
-1
lines changed

src/main/java/com/amazon/ion/IonReader.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,31 @@ public interface IonReader
447447
// In particular, does this move the cursor beyond the current value?
448448
// Also, this could be problematic to use since other value-extraction
449449
// methods are read-once, so one can't look at the value before calling this.
450-
// public String valueToString();
450+
// public String valueToString();
451+
452+
/**
453+
* Closes this reader and releases any system resources associated with it.
454+
* <p>
455+
* For readers created from an {@link java.io.InputStream}, this method will
456+
* close the underlying stream. For readers created from byte arrays or strings,
457+
* this method will release internal resources such as UTF-8 decoders.
458+
* <p>
459+
* After calling this method, the reader should not be used for any further
460+
* operations. Attempting to use a closed reader may result in undefined behavior.
461+
* <p>
462+
* This method makes {@code IonReader} compatible with try-with-resources statements:
463+
* <pre>{@code
464+
* try (IonReader reader = IonReaderBuilder.standard().build(inputStream)) {
465+
* // Use the reader
466+
* while (reader.next() != null) {
467+
* // Process values
468+
* }
469+
* } // Reader is automatically closed here
470+
* }</pre>
471+
*
472+
* @throws IOException if an I/O error occurs while closing the underlying stream
473+
*/
474+
@Override
475+
void close() throws IOException;
451476

452477
}
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
/*
2+
* Copyright 2007-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.amazon.ion;
17+
18+
import com.amazon.ion.system.IonReaderBuilder;
19+
import org.junit.Test;
20+
21+
import java.io.ByteArrayInputStream;
22+
import java.io.IOException;
23+
import java.io.InputStream;
24+
25+
import static org.junit.Assert.*;
26+
27+
/**
28+
* Tests that IonReader properly implements Closeable and can be used with try-with-resources.
29+
*/
30+
public class IonReaderCloseableTest {
31+
32+
@Test
33+
public void testIonReaderIsCloseable() {
34+
// Verify that IonReader extends Closeable
35+
assertTrue("IonReader should extend Closeable",
36+
java.io.Closeable.class.isAssignableFrom(IonReader.class));
37+
}
38+
39+
@Test
40+
public void testIonReaderIsAutoCloseable() {
41+
// Verify that IonReader extends AutoCloseable (through Closeable)
42+
assertTrue("IonReader should extend AutoCloseable",
43+
AutoCloseable.class.isAssignableFrom(IonReader.class));
44+
}
45+
46+
@Test
47+
public void testTryWithResourcesWithByteArray() throws IOException {
48+
byte[] ionData = "hello".getBytes();
49+
50+
// Test that IonReader can be used in try-with-resources
51+
try (IonReader reader = IonReaderBuilder.standard().build(ionData)) {
52+
assertNotNull("Reader should not be null", reader);
53+
// Use the reader
54+
IonType type = reader.next();
55+
assertEquals("Should read a symbol", IonType.SYMBOL, type);
56+
assertEquals("Should read 'hello'", "hello", reader.stringValue());
57+
} // Reader should be automatically closed here
58+
59+
// Test passes if no exception is thrown
60+
}
61+
62+
@Test
63+
public void testTryWithResourcesWithInputStream() throws IOException {
64+
byte[] ionData = "world".getBytes();
65+
InputStream inputStream = new ByteArrayInputStream(ionData);
66+
67+
// Test that IonReader can be used in try-with-resources with InputStream
68+
try (IonReader reader = IonReaderBuilder.standard().build(inputStream)) {
69+
assertNotNull("Reader should not be null", reader);
70+
// Use the reader
71+
IonType type = reader.next();
72+
assertEquals("Should read a symbol", IonType.SYMBOL, type);
73+
assertEquals("Should read 'world'", "world", reader.stringValue());
74+
} // Reader should be automatically closed here
75+
76+
// Test passes if no exception is thrown
77+
}
78+
79+
@Test
80+
public void testManualClose() throws IOException {
81+
byte[] ionData = "test".getBytes();
82+
IonReader reader = IonReaderBuilder.standard().build(ionData);
83+
84+
try {
85+
assertNotNull("Reader should not be null", reader);
86+
// Use the reader
87+
IonType type = reader.next();
88+
assertEquals("Should read a symbol", IonType.SYMBOL, type);
89+
assertEquals("Should read 'test'", "test", reader.stringValue());
90+
} finally {
91+
// Manually close the reader
92+
reader.close();
93+
}
94+
95+
// Test passes if no exception is thrown
96+
}
97+
98+
@Test
99+
public void testCloseWithInputStream() throws IOException {
100+
byte[] ionData = "closetest".getBytes();
101+
102+
// Create a custom InputStream that tracks if it was closed
103+
class TrackingInputStream extends ByteArrayInputStream {
104+
private boolean closed = false;
105+
106+
public TrackingInputStream(byte[] buf) {
107+
super(buf);
108+
}
109+
110+
@Override
111+
public void close() throws IOException {
112+
super.close();
113+
closed = true;
114+
}
115+
116+
public boolean isClosed() {
117+
return closed;
118+
}
119+
}
120+
121+
TrackingInputStream trackingStream = new TrackingInputStream(ionData);
122+
123+
try (IonReader reader = IonReaderBuilder.standard().build(trackingStream)) {
124+
// Use the reader
125+
reader.next();
126+
} // Reader and underlying stream should be closed here
127+
128+
assertTrue("Underlying InputStream should be closed", trackingStream.isClosed());
129+
}
130+
}

0 commit comments

Comments
 (0)