Skip to content

Commit

Permalink
support IOContext closing in GeneratorBase (#1094)
Browse files Browse the repository at this point in the history
  • Loading branch information
pjfanning authored Aug 31, 2023
1 parent 40cd6b7 commit 8093f43
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 27 deletions.
33 changes: 29 additions & 4 deletions src/main/java/com/fasterxml/jackson/core/base/GeneratorBase.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.fasterxml.jackson.core.base;

import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.core.json.DupDetector;
import com.fasterxml.jackson.core.json.JsonWriteContext;
import com.fasterxml.jackson.core.json.PackageVersion;
Expand Down Expand Up @@ -69,6 +70,9 @@ public abstract class GeneratorBase extends JsonGenerator
*/
protected int _features;

// since 2.16
protected final IOContext _ioContext;

/**
* Flag set to indicate that implicit conversion from number
* to JSON String is needed (as per
Expand Down Expand Up @@ -101,24 +105,38 @@ public abstract class GeneratorBase extends JsonGenerator
/**********************************************************
*/

@SuppressWarnings("deprecation")
@Deprecated // since 2.16
protected GeneratorBase(int features, ObjectCodec codec) {
this(features, codec, (IOContext) null);
}

// @since 2.16
@SuppressWarnings("deprecation")
protected GeneratorBase(int features, ObjectCodec codec, IOContext ioContext) {
super();
_features = features;
_objectCodec = codec;
_ioContext = ioContext;
DupDetector dups = Feature.STRICT_DUPLICATE_DETECTION.enabledIn(features)
? DupDetector.rootDetector(this) : null;
_writeContext = JsonWriteContext.createRootContext(dups);
_cfgNumbersAsStrings = Feature.WRITE_NUMBERS_AS_STRINGS.enabledIn(features);
}

// @since 2.5
@SuppressWarnings("deprecation")
@Deprecated // since 2.16
protected GeneratorBase(int features, ObjectCodec codec, JsonWriteContext ctxt) {
this(features, codec, null, ctxt);
}

// @since 2.16
@SuppressWarnings("deprecation")
protected GeneratorBase(int features, ObjectCodec codec, IOContext ioContext, JsonWriteContext jsonWriteContext) {
super();
_features = features;
_objectCodec = codec;
_writeContext = ctxt;
_ioContext = ioContext;
_writeContext = jsonWriteContext;
_cfgNumbersAsStrings = Feature.WRITE_NUMBERS_AS_STRINGS.enabledIn(features);
}

Expand Down Expand Up @@ -413,7 +431,14 @@ public void writeTree(TreeNode rootNode) throws IOException {
*/

@Override public abstract void flush() throws IOException;
@Override public void close() throws IOException { _closed = true; }
@Override public void close() throws IOException {
if (!_closed) {
if (_ioContext != null) {
_ioContext.close();
}
_closed = true;
}
}
@Override public boolean isClosed() { return _closed; }

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,6 @@ public abstract class JsonGeneratorImpl extends GeneratorBase
/**********************************************************
*/

protected final IOContext _ioContext;

/**
* @since 2.16
*/
Expand Down Expand Up @@ -120,19 +118,10 @@ public abstract class JsonGeneratorImpl extends GeneratorBase
/**********************************************************
*/

@Override
public void close() throws IOException {
if (!isClosed()) {
super.close();
_ioContext.close();
}
}

@SuppressWarnings("deprecation")
public JsonGeneratorImpl(IOContext ctxt, int features, ObjectCodec codec)
{
super(features, codec);
_ioContext = ctxt;
super(features, codec, ctxt);
_streamWriteConstraints = ctxt.streamWriteConstraints();
if (Feature.ESCAPE_NON_ASCII.enabledIn(features)) {
// inlined `setHighestNonEscapedChar()`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,28 +12,28 @@

public class BufferRecyclerPoolTest extends BaseTest
{
public void testNoOp() {
public void testNoOp() throws Exception {
// no-op pool doesn't actually pool anything, so avoid checking it
checkBufferRecyclerPoolImpl(BufferRecyclerPool.NonRecyclingPool.shared(), false);
}

public void testThreadLocal() {
public void testThreadLocal() throws Exception {
checkBufferRecyclerPoolImpl(BufferRecyclerPool.ThreadLocalPool.shared(), true);
}

public void testLockFree() {
public void testLockFree() throws Exception {
checkBufferRecyclerPoolImpl(BufferRecyclerPool.LockFreePool.nonShared(), true);
}

public void testConcurrentDequeue() {
public void testConcurrentDequeue() throws Exception {
checkBufferRecyclerPoolImpl(BufferRecyclerPool.ConcurrentDequePool.nonShared(), true);
}

public void testBounded() {
public void testBounded() throws Exception {
checkBufferRecyclerPoolImpl(BufferRecyclerPool.BoundedPool.nonShared(1), true);
}

private void checkBufferRecyclerPoolImpl(BufferRecyclerPool pool, boolean checkPooledResource) {
private void checkBufferRecyclerPoolImpl(BufferRecyclerPool pool, boolean checkPooledResource) throws Exception {
JsonFactory jsonFactory = JsonFactory.builder()
.bufferRecyclerPool(pool)
.build();
Expand All @@ -50,23 +50,21 @@ private void checkBufferRecyclerPoolImpl(BufferRecyclerPool pool, boolean checkP
}
}

protected final BufferRecycler write(Object value, JsonFactory jsonFactory, int expectedSize) {
private BufferRecycler write(Object value, JsonFactory jsonFactory, int expectedSize) throws Exception {
BufferRecycler bufferRecycler;
NopOutputStream out = new NopOutputStream();
try (JsonGenerator gen = jsonFactory.createGenerator(out)) {
bufferRecycler = ((JsonGeneratorImpl) gen).ioContext()._bufferRecycler;
gen.writeObject(value);
} catch (IOException e) {
throw new RuntimeException(e);
}
assertEquals(expectedSize, out.size);
return bufferRecycler;
}

public class NopOutputStream extends OutputStream {
private static class NopOutputStream extends OutputStream {
protected int size = 0;

public NopOutputStream() { }
NopOutputStream() { }

@Override
public void write(int b) throws IOException { ++size; }
Expand Down

0 comments on commit 8093f43

Please sign in to comment.