Skip to content

Commit

Permalink
fix FasterXML#99 do not close stream when autoclose is disabled
Browse files Browse the repository at this point in the history
  • Loading branch information
vboulaye committed Oct 20, 2018
1 parent 220203d commit 08d9da2
Show file tree
Hide file tree
Showing 4 changed files with 216 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,21 @@ public void close() throws IOException
_emitter.emit(new DocumentEndEvent(null, null, false));
_emitter.emit(new StreamEndEvent(null, null));
super.close();
_writer.close();

/* 25-Nov-2008, tatus: As per [JACKSON-16] we are not to call close()
* on the underlying Reader, unless we "own" it, or auto-closing
* feature is enabled.
* One downside: when using UTF8Writer, underlying buffer(s)
* may not be properly recycled if we don't close the writer.
*/
if (_writer != null) {
if (_ioContext.isResourceManaged() || isEnabled(JsonGenerator.Feature.AUTO_CLOSE_TARGET)) {
_writer.close();
} else if (isEnabled(JsonGenerator.Feature.FLUSH_PASSED_TO_STREAM)) {
// If we can't close it, we should at least flush
_writer.flush();
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,16 @@ public Version version() {

@Override
protected void _closeInput() throws IOException {
_reader.close();
/* 25-Nov-2008, tatus: As per [JACKSON-16] we are not to call close()
* on the underlying Reader, unless we "own" it, or auto-closing
* feature is enabled.
* One downside is that when using our optimized
* Reader (granted, we only do that for UTF-32...) this
* means that buffer recycling won't work correctly.
*/
if (_ioContext.isResourceManaged() || isEnabled(JsonParser.Feature.AUTO_CLOSE_SOURCE)) {
_reader.close();
}
}

/*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
package com.fasterxml.jackson.dataformat.yaml.deser;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.StringReader;

import org.junit.Assert;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.ModuleTestBase;

public class ParserAutoCloseTest extends ModuleTestBase {

public void testParseReaderWithAutoClose() throws IOException {
ObjectMapper yamlMapper = newObjectMapper();

CloseTrackerReader reader = new CloseTrackerReader("foo:bar");
yamlMapper.readTree(reader);

Assert.assertEquals(true, reader.isClosed());
}

public void testParseStreamWithAutoClose() throws IOException {
ObjectMapper yamlMapper = newObjectMapper();

CloseTrackerOutputStream stream = new CloseTrackerOutputStream("foo:bar");
yamlMapper.readTree(stream);

Assert.assertEquals(true, stream.isClosed());
}

public void testParseReaderWithoutAutoClose() throws IOException {
ObjectMapper yamlMapper = newObjectMapper()
.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);

CloseTrackerReader reader = new CloseTrackerReader("foo:bar");
yamlMapper.readTree(reader);

Assert.assertEquals(false, reader.isClosed());
}


public void testParseStreamWithoutAutoClose() throws IOException {
ObjectMapper yamlMapper = newObjectMapper()
.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);

CloseTrackerOutputStream stream = new CloseTrackerOutputStream("foo:bar");
yamlMapper.readTree(stream);

Assert.assertEquals(false, stream.isClosed());
}

public static class CloseTrackerReader extends StringReader {
private boolean closed;

public CloseTrackerReader(String s) {
super(s);
}

@Override
public void close() {
closed = true;
super.close();
}

public boolean isClosed() {
return closed;
}
}


public static class CloseTrackerOutputStream extends ByteArrayInputStream {
private boolean closed;

public CloseTrackerOutputStream(String s) {
super(s.getBytes());
}

@Override
public void close() throws IOException {
closed = true;
super.close();
}

public boolean isClosed() {
return closed;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package com.fasterxml.jackson.dataformat.yaml.ser;

import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;

import org.junit.Assert;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.ModuleTestBase;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;

public class GeneratorAutoCloseTest extends ModuleTestBase {

private Pojo pojo = new Pojo("bar");

public void testGenerateWriterWithoAutoCloseTarget() throws IOException {
CloseTrackerWriter writer = new CloseTrackerWriter();
ObjectMapper yamlMapper = newObjectMapper();
yamlMapper.writeValue(writer, pojo);
Assert.assertEquals(true, writer.isClosed());
}

public void testGenerateOutputStreamWithAutoCloseTarget() throws IOException {
CloseTrackerOutputStream stream = new CloseTrackerOutputStream();
ObjectMapper yamlMapper = newObjectMapper();
yamlMapper.writeValue(stream, pojo);
Assert.assertEquals(true, stream.isClosed());
}

public void testGenerateWriterWithoutAutoCloseTarget() throws IOException {
CloseTrackerWriter writer = new CloseTrackerWriter();
ObjectMapper yamlMapper = newObjectMapper()
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
yamlMapper.writeValue(writer, pojo);
Assert.assertEquals(false, writer.isClosed());
}

public void testGenerateOutputStreamWithoutAutoCloseTarget() throws IOException {
CloseTrackerOutputStream stream = new CloseTrackerOutputStream();
ObjectMapper yamlMapper = newObjectMapper()
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
yamlMapper.writeValue(stream, pojo);
Assert.assertEquals(false, stream.isClosed());
}

public void testGenerateOutputStreamWithoutAutoCloseTargetOnFactory() throws IOException {
CloseTrackerOutputStream stream = new CloseTrackerOutputStream();
ObjectMapper yamlMapper = new ObjectMapper(
new YAMLFactory()
.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
);
yamlMapper.writeValue(stream, pojo);
Assert.assertEquals(false, stream.isClosed());
}


static class CloseTrackerOutputStream extends OutputStream {
private boolean closed;

@Override
public void write(int b) throws IOException {

}

@Override
public void close() throws IOException {
closed = true;
super.close();
}

public boolean isClosed() {
return closed;
}
}

static class CloseTrackerWriter extends StringWriter {
private boolean closed;


@Override
public void close() throws IOException {
closed = true;
super.close();
}

public boolean isClosed() {
return closed;
}
}

static class Pojo {

public final String foo;

Pojo(final String foo) {
this.foo = foo;
}
}
}

0 comments on commit 08d9da2

Please sign in to comment.