AvroFactory.java
package tools.jackson.dataformat.avro;
import java.io.*;
import tools.jackson.dataformat.avro.apacheimpl.AvroRecyclerPools;
import tools.jackson.core.*;
import tools.jackson.core.base.BinaryTSFactory;
import tools.jackson.core.io.IOContext;
import tools.jackson.core.util.RecyclerPool;
import tools.jackson.dataformat.avro.apacheimpl.ApacheAvroParserImpl;
import tools.jackson.dataformat.avro.apacheimpl.ApacheCodecRecycler;
import tools.jackson.dataformat.avro.deser.*;
/**
* Default {@link TokenStreamFactory} implementation for encoding/decoding Avro
* content, uses native Jackson encoder/decoder.
*/
public class AvroFactory
extends BinaryTSFactory
implements java.io.Serializable
{
private static final long serialVersionUID = 1L;
public final static String FORMAT_NAME_AVRO = "avro";
/**
* Bitfield (set of flags) of all parser features that are enabled
* by default.
*/
final static int DEFAULT_AVRO_PARSER_FEATURE_FLAGS = AvroReadFeature.collectDefaults();
/**
* Bitfield (set of flags) of all generator features that are enabled
* by default.
*/
final static int DEFAULT_AVRO_GENERATOR_FEATURE_FLAGS = AvroWriteFeature.collectDefaults();
/*
/**********************************************************
/* Configuration
/**********************************************************
*/
/**
* @since 2.16
*/
protected RecyclerPool<ApacheCodecRecycler> _avroRecyclerPool
= AvroRecyclerPools.defaultPool();
/**
* Flag that is set if Apache Avro lib's decoder is to be used for decoding;
* `false` to use Jackson native Avro decoder.
*/
protected boolean _useApacheLibDecoder;
/*
/**********************************************************
/* Factory construction, configuration
/**********************************************************
*/
/**
* Default constructor used to create factory instances.
* Creation of a factory instance is a light-weight operation,
* but it is still a good idea to reuse limited number of
* factory instances (and quite often just a single instance):
* factories are used as context for storing some reused
* processing objects (such as symbol tables parsers use)
* and this reuse only works within context of a single
* factory instance.
*/
public AvroFactory()
{
// 09-Jan-2017, tatu: We must actually create and pass builder to be able to change
// one of JsonGenerator.Features (See builder for details)
super(new AvroFactoryBuilder());
}
protected AvroFactory(AvroFactory src)
{
super(src);
_useApacheLibDecoder = src._useApacheLibDecoder;
}
/**
* Constructors used by {@link AvroFactoryBuilder} for instantiation.
*
* @since 3.0
*/
protected AvroFactory(AvroFactoryBuilder b)
{
super(b);
_useApacheLibDecoder = b.useApacheLibDecoder();
}
@Override
public AvroFactoryBuilder rebuild() {
return new AvroFactoryBuilder(this);
}
/**
* Main factory method to use for constructing a builder for creating
* {@link AvroFactory} instances with different configuration.
* Builder is initialized to defaults and this is equivalent to calling
* {@link #builderWithNativeDecoder}.
*/
public static AvroFactoryBuilder builder() {
return new AvroFactoryBuilder();
}
/**
* Main factory method to use for constructing a builder for creating
* {@link AvroFactory} instances with different configuration,
* initialized to use Apache Avro library codec for decoding content
* (instead of Jackson native decoder).
*/
public static AvroFactoryBuilder builderWithApacheDecoder() {
return new AvroFactoryBuilder(true);
}
/**
* Main factory method to use for constructing a builder for creating
* {@link AvroFactory} instances with different configuration,
* initialized to use Jackson antive codec for decoding content
* (instead of Apache Avro library decoder).
*/
public static AvroFactoryBuilder builderWithNativeDecoder() {
return new AvroFactoryBuilder(false);
}
@Override
public AvroFactory copy() {
return new AvroFactory(this);
}
/**
* Instances are immutable so just return `this`
*/
@Override
public TokenStreamFactory snapshot() {
return this;
}
@Override // since 2.10 (should have been earlier)
public boolean canHandleBinaryNatively() {
return true;
}
/*
/**********************************************************
/* Serializable overrides
/**********************************************************
*/
/**
* Method that we need to override to actually make restoration go
* through constructors etc.
* Also: must be overridden by sub-classes as well.
*/
protected Object readResolve() {
return new AvroFactory(this);
}
/*
/**********************************************************
/* Basic introspection
/**********************************************************
*/
@Override
public Version version() {
return PackageVersion.VERSION;
}
// Yes, Avro is strictly positional based on schema
@Override
public boolean requiresPropertyOrdering() {
return true;
}
@Override
public boolean canParseAsync() {
// 30-Sep-2017, tatu: No async implementation exists yet
return false;
}
/**
* Checked whether specified parser feature is enabled.
*/
public final boolean isEnabled(AvroReadFeature f) {
return (_formatReadFeatures & f.getMask()) != 0;
}
/**
* Check whether specified generator feature is enabled.
*/
public final boolean isEnabled(AvroWriteFeature f) {
return (_formatWriteFeatures & f.getMask()) != 0;
}
/*
/**********************************************************
/* Data format support
/**********************************************************
*/
@Override
public String getFormatName() {
return FORMAT_NAME_AVRO;
}
@Override
public boolean canUseSchema(FormatSchema schema) {
return (schema instanceof AvroSchema);
}
@Override
public Class<AvroReadFeature> getFormatReadFeatureType() {
return AvroReadFeature.class;
}
@Override
public Class<AvroWriteFeature> getFormatWriteFeatureType() {
return AvroWriteFeature.class;
}
/*
/******************************************************
/* Factory method impls: parsers
/******************************************************
*/
/**
* Overridable factory method that actually instantiates desired
* parser.
*/
@Override
protected AvroParser _createParser(ObjectReadContext readCtxt, IOContext ioCtxt,
InputStream in) throws JacksonException
{
if (_useApacheLibDecoder) {
return new ApacheAvroParserImpl(readCtxt, ioCtxt,
readCtxt.getStreamReadFeatures(_streamReadFeatures),
readCtxt.getFormatReadFeatures(_formatReadFeatures),
_avroRecyclerPool.acquireAndLinkPooled(),
(AvroSchema) readCtxt.getSchema(),
in);
}
return new JacksonAvroParserImpl(readCtxt, ioCtxt,
readCtxt.getStreamReadFeatures(_streamReadFeatures),
readCtxt.getFormatReadFeatures(_formatReadFeatures),
(AvroSchema) readCtxt.getSchema(),
in);
}
@Override
protected AvroParser _createParser(ObjectReadContext readCtxt, IOContext ioCtxt,
byte[] data, int offset, int len)
throws JacksonException
{
if (_useApacheLibDecoder) {
return new ApacheAvroParserImpl(readCtxt, ioCtxt,
readCtxt.getStreamReadFeatures(_streamReadFeatures),
readCtxt.getFormatReadFeatures(_formatReadFeatures),
_avroRecyclerPool.acquireAndLinkPooled(),
(AvroSchema) readCtxt.getSchema(),
data, offset, len);
}
return new JacksonAvroParserImpl(readCtxt, ioCtxt,
readCtxt.getStreamReadFeatures(_streamReadFeatures),
readCtxt.getFormatReadFeatures(_formatReadFeatures),
(AvroSchema) readCtxt.getSchema(),
data, offset, len);
}
@Override
protected JsonParser _createParser(ObjectReadContext readCtxt, IOContext ioCtxt,
DataInput input)
{
// 30-Sep-2017, tatu: As of now not supported although should be quite possible
// to support
return _unsupported();
}
/*
/******************************************************
/* Factory method impls: generators
/******************************************************
*/
@Override
protected JsonGenerator _createGenerator(ObjectWriteContext writeCtxt,
IOContext ioCtxt, OutputStream out)
throws JacksonException
{
return new AvroGenerator(writeCtxt, ioCtxt,
writeCtxt.getStreamWriteFeatures(_streamWriteFeatures),
writeCtxt.getFormatWriteFeatures(_formatWriteFeatures),
_avroRecyclerPool.acquireAndLinkPooled(),
(AvroSchema) writeCtxt.getSchema(),
out);
}
}