TomlFactory.java
package tools.jackson.dataformat.toml;
import java.io.*;
import tools.jackson.core.*;
import tools.jackson.core.TokenStreamLocation;
import tools.jackson.core.base.TextualTSFactory;
import tools.jackson.core.io.GuardedOutputStream;
import tools.jackson.core.io.IOContext;
import tools.jackson.core.io.UTF8Writer;
import tools.jackson.databind.node.ObjectNode;
import tools.jackson.databind.node.TreeTraversingParser;
public final class TomlFactory extends TextualTSFactory
{
private final static long serialVersionUID = 1L;
public final static String FORMAT_NAME_TOML = "toml";
/**
* Bitfield (set of flags) of all generator features that are enabled
* by default.
*/
final static int DEFAULT_TOML_PARSER_FEATURE_FLAGS = TomlReadFeature.collectDefaults();
/**
* Bitfield (set of flags) of all generator features that are enabled
* by default.
*/
final static int DEFAULT_TOML_GENERATOR_FEATURE_FLAGS = TomlWriteFeature.collectDefaults();
/*
/**********************************************************************
/* Factory construction, configuration
/**********************************************************************
*/
public TomlFactory() {
super(StreamReadConstraints.defaults(), StreamWriteConstraints.defaults(),
ErrorReportConfiguration.defaults(),
DEFAULT_TOML_PARSER_FEATURE_FLAGS, DEFAULT_TOML_GENERATOR_FEATURE_FLAGS);
}
TomlFactory(TomlFactory src) {
super(src);
}
/**
* Constructors used by {@link TomlFactoryBuilder} for instantiation.
*
* @since 3.0
*/
TomlFactory(TomlFactoryBuilder b) {
super(b);
}
@Override
public TomlFactoryBuilder rebuild() {
return new TomlFactoryBuilder(this);
}
/**
* Main factory method to use for constructing {@link TomlFactory} instances with
* different configuration.
*/
public static TomlFactoryBuilder builder() {
return new TomlFactoryBuilder();
}
@Override
public TomlFactory copy() {
return new TomlFactory(this);
}
/**
* Instances are immutable so just return `this`
*/
@Override
public TokenStreamFactory snapshot() {
return this;
}
/*
/**********************************************************************
/* Serializable overrides
/**********************************************************************
*/
/**
* Method that we need to override to actually make restoration go
* through constructors etc.
*/
protected Object readResolve() {
return new TomlFactory(this);
}
/*
/**********************************************************************
/* Capability introspection
/**********************************************************************
*/
@Override
public Version version() {
return PackageVersion.VERSION;
}
@Override
public boolean requiresPropertyOrdering() {
return false;
}
@Override
public boolean canUseCharArrays() {
return false;
}
@Override
public boolean canParseAsync() {
return false;
}
/*
/**********************************************************************
/* Format support
/**********************************************************************
*/
@Override
public String getFormatName() {
return FORMAT_NAME_TOML;
}
@Override
public boolean canUseSchema(FormatSchema schema) {
return false;
}
@Override
public Class<? extends FormatFeature> getFormatReadFeatureType() {
return TomlReadFeature.class;
}
@Override
public Class<? extends FormatFeature> getFormatWriteFeatureType() {
return TomlWriteFeature.class;
}
@Override
public int getFormatReadFeatures() {
return _formatReadFeatures;
}
@Override
public int getFormatWriteFeatures() {
return _formatWriteFeatures;
}
public boolean isEnabled(TomlReadFeature f) {
return (_formatReadFeatures & f.getMask()) != 0;
}
public boolean isEnabled(TomlWriteFeature f) {
return (_formatWriteFeatures & f.getMask()) != 0;
}
/*
/**********************************************************************
/* Overridden internal factory methods, parser
/**********************************************************************
*/
@Override
protected JsonParser _createParser(ObjectReadContext readCtxt, IOContext ctxt, InputStream in) throws JacksonException {
// "A TOML file must be a valid UTF-8 encoded Unicode document."
// Reader is constructed (and hence owned) by us, so it must always be closed to
// have its read buffer recycled. A source Jackson opened (File/Path) is closed by
// the base factory when construction fails [dataformats-text#720], so the reader
// must not close it too; we close that source only after a successful parse.
// A caller-owned stream is closed with the reader when auto-close is enabled,
// because the base factory does not close caller sources.
final boolean managed = ctxt.isResourceManaged();
final boolean closeStreamWithReader = !managed
&& StreamReadFeature.AUTO_CLOSE_SOURCE.enabledIn(
readCtxt.getStreamReadFeatures(_streamReadFeatures));
JsonParser parser = _createParser(readCtxt, ctxt,
UTF8Reader.construct(ctxt, in, closeStreamWithReader), true);
if (managed) {
try {
in.close();
} catch (IOException e) {
throw _wrapIOFailure(e);
}
}
return parser;
}
@Override
protected JsonParser _createParser(ObjectReadContext readCtxt, IOContext ctxt, Reader r) throws JacksonException {
// Reader is the caller's, so only close it if auto-closing is enabled
return _createParser(readCtxt, ctxt, r, _autoCloseSource(readCtxt, ctxt));
}
private JsonParser _createParser(ObjectReadContext readCtxt, IOContext ctxt, Reader r,
boolean closeReader) throws JacksonException {
try {
ObjectNode node = parse(readCtxt, ctxt, r, closeReader);
return new TreeTraversingParser(node, readCtxt, ctxt.streamReadConstraints());
} finally {
ctxt.close();
}
}
@Override
protected JsonParser _createParser(ObjectReadContext readCtxt, IOContext ctxt, byte[] data, int offset, int len) throws JacksonException {
return _createParser(readCtxt, ctxt, UTF8Reader.construct(data, offset, len));
}
@Override
protected JsonParser _createParser(ObjectReadContext readCtxt, IOContext ctxt, char[] data, int offset, int len, boolean recyclable) throws JacksonException {
return _createParser(readCtxt, ctxt, new CharArrayReader(data, offset, len));
}
@Override
protected JsonParser _createParser(ObjectReadContext readCtxt, IOContext ctxt, DataInput input) throws JacksonException {
return _unsupported();
}
/*
/**********************************************************************
/* Overridden internal factory methods, generator
/**********************************************************************
*/
@Override
protected JsonGenerator _createGenerator(ObjectWriteContext writeCtxt, IOContext ioCtxt, Writer out) throws JacksonException {
return new TomlGenerator(writeCtxt, ioCtxt,
writeCtxt.getStreamWriteFeatures(_streamWriteFeatures),
writeCtxt.getFormatWriteFeatures(_formatWriteFeatures),
out);
}
@Override
protected JsonGenerator _createUTF8Generator(ObjectWriteContext writeCtxt, IOContext ioCtxt, OutputStream out) throws JacksonException {
// [dataformats-text#735]: Writer is constructed (and hence owned) by us, so the
// generator must always flush and close it -- that hands its pending content over
// and recycles its buffer. It is shielded from the caller's stream, which the
// generator itself flushes or closes as per `FLUSH_PASSED_TO_STREAM` and
// `AUTO_CLOSE_TARGET` (as enabled at that point).
return new TomlGenerator(writeCtxt, ioCtxt,
writeCtxt.getStreamWriteFeatures(_streamWriteFeatures),
writeCtxt.getFormatWriteFeatures(_formatWriteFeatures),
new UTF8Writer(ioCtxt, new GuardedOutputStream(out)), out);
}
@Override
protected Writer _createWriter(IOContext ioCtxt, OutputStream out, JsonEncoding enc) throws JacksonException {
// "A TOML file must be a valid UTF-8 encoded Unicode document."
return new UTF8Writer(ioCtxt, out);
}
/*
/**********************************************************************
/* Low-level methods for reading/writing TOML
/**********************************************************************
*/
private boolean _autoCloseSource(ObjectReadContext readCtxt, IOContext ctxt) {
return ctxt.isResourceManaged()
|| StreamReadFeature.AUTO_CLOSE_SOURCE.enabledIn(
readCtxt.getStreamReadFeatures(_streamReadFeatures));
}
private ObjectNode parse(ObjectReadContext readCtxt, IOContext ctxt, Reader r0,
boolean closeReader) {
int readFeatures = readCtxt.getFormatReadFeatures(DEFAULT_TOML_PARSER_FEATURE_FLAGS);
try {
if (closeReader) {
try (Reader r = r0) {
return TomlParser.parse(this, ctxt, readFeatures, r);
}
} else {
return TomlParser.parse(this, ctxt, readFeatures, r0);
}
} catch (CharConversionException e) {
TokenStreamLocation location;
if (e instanceof UTF8Reader.InvalidUTF8Exception utf8Ex) {
location = new TokenStreamLocation(ctxt.contentReference(),
utf8Ex.byteOffset, utf8Ex.charOffset, -1, -1);
} else {
location = new TokenStreamLocation(ctxt.contentReference(), -1, -1, -1, -1);
}
throw new TomlStreamReadException(null, e.getMessage(), location, e);
} catch (IOException e) {
throw _wrapIOFailure(e);
}
}
}