package com.fasterxml.jackson.dataformat.avro;
import java.io.*;
import java.net.URL;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.format.InputAccessor;
import com.fasterxml.jackson.core.format.MatchStrength;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.dataformat.avro.deser.*;
Default JsonFactory
implementation for encoding/decoding Avro content, uses native Jackson encoder/decoder. See Also:
/**
* Default {@link JsonFactory} implementation for encoding/decoding Avro
* content, uses native Jackson encoder/decoder.
*
* @see com.fasterxml.jackson.dataformat.avro.apacheimpl.ApacheAvroFactory
*/
public class AvroFactory extends JsonFactory
{
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.
/**
* Bitfield (set of flags) of all parser features that are enabled
* by default.
*/
final static int DEFAULT_AVRO_PARSER_FEATURE_FLAGS = AvroParser.Feature.collectDefaults();
Bitfield (set of flags) of all generator features that are enabled
by default.
/**
* Bitfield (set of flags) of all generator features that are enabled
* by default.
*/
final static int DEFAULT_AVRO_GENERATOR_FEATURE_FLAGS = AvroGenerator.Feature.collectDefaults();
/*
/**********************************************************
/* Configuration
/**********************************************************
*/
protected int _avroParserFeatures;
protected int _avroGeneratorFeatures;
Flag that is set if Apache Avro lib's decoder is to be used for decoding;
`false` to use Jackson native Avro decoder.
Since: 2.9
/**
* Flag that is set if Apache Avro lib's decoder is to be used for decoding;
* `false` to use Jackson native Avro decoder.
*
* @since 2.9
*/
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.
/**
* 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(), false);
_avroParserFeatures = DEFAULT_AVRO_PARSER_FEATURE_FLAGS;
_avroGeneratorFeatures = DEFAULT_AVRO_GENERATOR_FEATURE_FLAGS;
_useApacheLibDecoder = false;
}
public AvroFactory(ObjectCodec oc)
{
super(oc);
_avroParserFeatures = DEFAULT_AVRO_PARSER_FEATURE_FLAGS;
_avroGeneratorFeatures = DEFAULT_AVRO_GENERATOR_FEATURE_FLAGS;
_useApacheLibDecoder = false;
/* 04-Mar-2013, tatu: Content auto-closing is unfortunately a feature
* that works poorly with Avro error reporting, and generally
* manages to replace actual failure with a bogus one when
* missing "END_OBJECT"s (etc) are called. So let's default
* it to disabled, unlike for most JsonFactory sub-types.
*/
disable(JsonGenerator.Feature.AUTO_CLOSE_JSON_CONTENT);
}
protected AvroFactory(AvroFactory src, ObjectCodec oc)
{
super(src, oc);
_avroParserFeatures = src._avroParserFeatures;
_avroGeneratorFeatures = src._avroGeneratorFeatures;
_useApacheLibDecoder = src._useApacheLibDecoder;
}
Constructors used by AvroFactoryBuilder
for instantiation. Since: 2.9
/**
* Constructors used by {@link AvroFactoryBuilder} for instantiation.
*
* @since 2.9
*/
protected AvroFactory(AvroFactoryBuilder b)
{
super(b, false);
_avroParserFeatures = b.formatParserFeaturesMask();
_avroGeneratorFeatures = b.formatGeneratorFeaturesMask();
_useApacheLibDecoder = b.useApacheLibDecoder();
}
@Override
public AvroFactoryBuilder rebuild() {
return new AvroFactoryBuilder(this);
}
Main factory method to use for constructing a builder for creating AvroFactory
instances with different configuration. Builder is initialized to defaults and this is equivalent to calling builderWithNativeDecoder
. /**
* 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 AvroFactory
instances with different configuration, initialized to use Apache Avro library codec for decoding content (instead of Jackson native decoder). /**
* 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 AvroFactory
instances with different configuration, initialized to use Jackson antive codec for decoding content (instead of Apache Avro library decoder). /**
* 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()
{
_checkInvalidCopy(AvroFactory.class);
return new AvroFactory(this, null);
}
/*
/**********************************************************
/* Capability introspection
/**********************************************************
*/
// Yes, Avro is strictly positional based on schema
@Override
public boolean requiresPropertyOrdering() {
return true;
}
@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.
/**
* Method that we need to override to actually make restoration go
* through constructors etc.
* Also: must be overridden by sub-classes as well.
*/
@Override
protected Object readResolve() {
return new AvroFactory(this, _objectCodec);
}
/*
/**********************************************************
/* Versioned
/**********************************************************
*/
@Override
public Version version() {
return PackageVersion.VERSION;
}
/*
/**********************************************************
/* Format detection functionality
/**********************************************************
*/
@Override
public String getFormatName() {
return FORMAT_NAME_AVRO;
}
@Override
public boolean canUseSchema(FormatSchema schema) {
return (schema instanceof AvroSchema);
}
Sub-classes need to override this method
/**
* Sub-classes need to override this method
*/
@Override
public MatchStrength hasFormat(InputAccessor acc) throws IOException
{
// TODO, if possible... probably isn't?
return MatchStrength.INCONCLUSIVE;
}
/*
/**********************************************************
/* Configuration, parser settings
/**********************************************************
*/
Method for enabling or disabling specified parser feature (check Feature
for list of features) /**
* Method for enabling or disabling specified parser feature
* (check {@link AvroParser.Feature} for list of features)
*/
public final AvroFactory configure(AvroParser.Feature f, boolean state)
{
if (state) {
enable(f);
} else {
disable(f);
}
return this;
}
Method for enabling specified parser feature (check Feature
for list of features) /**
* Method for enabling specified parser feature
* (check {@link AvroParser.Feature} for list of features)
*/
public AvroFactory enable(AvroParser.Feature f) {
_avroParserFeatures |= f.getMask();
return this;
}
Method for disabling specified parser features (check Feature
for list of features) /**
* Method for disabling specified parser features
* (check {@link AvroParser.Feature} for list of features)
*/
public AvroFactory disable(AvroParser.Feature f) {
_avroParserFeatures &= ~f.getMask();
return this;
}
Checked whether specified parser feature is enabled.
/**
* Checked whether specified parser feature is enabled.
*/
public final boolean isEnabled(AvroParser.Feature f) {
return (_avroParserFeatures & f.getMask()) != 0;
}
@Override
public int getFormatParserFeatures() {
return _avroParserFeatures;
}
/*
/**********************************************************
/* Configuration, generator settings
/**********************************************************
*/
Method for enabling or disabling specified generator feature (check Feature
for list of features) /**
* Method for enabling or disabling specified generator feature
* (check {@link AvroGenerator.Feature} for list of features)
*/
public final AvroFactory configure(AvroGenerator.Feature f, boolean state) {
if (state) {
enable(f);
} else {
disable(f);
}
return this;
}
Method for enabling specified generator features (check Feature
for list of features) /**
* Method for enabling specified generator features
* (check {@link AvroGenerator.Feature} for list of features)
*/
public AvroFactory enable(AvroGenerator.Feature f) {
_avroGeneratorFeatures |= f.getMask();
return this;
}
Method for disabling specified generator feature (check Feature
for list of features) /**
* Method for disabling specified generator feature
* (check {@link AvroGenerator.Feature} for list of features)
*/
public AvroFactory disable(AvroGenerator.Feature f) {
_avroGeneratorFeatures &= ~f.getMask();
return this;
}
Check whether specified generator feature is enabled.
/**
* Check whether specified generator feature is enabled.
*/
public final boolean isEnabled(AvroGenerator.Feature f) {
return (_avroGeneratorFeatures & f.getMask()) != 0;
}
@Override
public int getFormatGeneratorFeatures() {
return _avroGeneratorFeatures;
}
/*
/**********************************************************
/* Overridden parser factory methods
/**********************************************************
*/
@SuppressWarnings("resource")
@Override
public AvroParser createParser(File f) throws IOException {
final IOContext ctxt = _createContext(f, true);
return _createParser(_decorate(new FileInputStream(f), ctxt), ctxt);
}
@Override
public AvroParser createParser(URL url) throws IOException {
final IOContext ctxt = _createContext(url, true);
return _createParser(_decorate(_optimizedStreamFromURL(url), ctxt), ctxt);
}
@Override
public AvroParser createParser(InputStream in) throws IOException {
final IOContext ctxt = _createContext(in, false);
return _createParser(_decorate(in, ctxt), ctxt);
}
//public JsonParser createParser(Reader r)
@Override
public AvroParser createParser(byte[] data) throws IOException {
return createParser(data, 0, data.length);
}
@SuppressWarnings("resource")
@Override
public AvroParser createParser(byte[] data, int offset, int len) throws IOException {
IOContext ctxt = _createContext(data, true);
if (_inputDecorator != null) {
InputStream in = _inputDecorator.decorate(ctxt, data, 0, data.length);
if (in != null) {
return _createParser(in, ctxt);
}
}
return _createParser(data, offset, len, ctxt);
}
/*
/**********************************************************
/* Overridden generator factory methods
/**********************************************************
*/
note: co-variant return type
/**
*<p>
* note: co-variant return type
*/
@Override
public AvroGenerator createGenerator(OutputStream out, JsonEncoding enc) throws IOException {
return createGenerator(out);
}
Since Avro format always uses UTF-8 internally, no encoding need
to be passed to this method.
/**
* Since Avro format always uses UTF-8 internally, no encoding need
* to be passed to this method.
*/
@Override
public AvroGenerator createGenerator(OutputStream out) throws IOException
{
// false -> we won't manage the stream unless explicitly directed to
IOContext ctxt = _createContext(out, false);
return _createGenerator(_decorate(out, ctxt), ctxt);
}
/*
/******************************************************
/* Overridden internal factory methods
/******************************************************
*/
//protected IOContext _createContext(Object srcRef, boolean resourceManaged)
Overridable factory method that actually instantiates desired
parser.
/**
* Overridable factory method that actually instantiates desired
* parser.
*/
@Override
protected AvroParser _createParser(InputStream in, IOContext ctxt) throws IOException {
// !!! 21-Apr-2017, tatu: make configurable
return new JacksonAvroParserImpl(ctxt, _parserFeatures, _avroParserFeatures,
// return new ApacheAvroParserImpl(ctxt, _parserFeatures, _avroParserFeatures,
_objectCodec, in);
}
@Override
protected JsonParser _createParser(Reader r, IOContext ctxt) throws IOException {
return _nonByteSource();
}
@Override
protected JsonParser _createParser(char[] data, int offset, int len, IOContext ctxt,
boolean recyclable) throws IOException {
return _nonByteSource();
}
@Override
protected AvroParser _createParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException {
// !!! 21-Apr-2017, tatu: make configurable
return new JacksonAvroParserImpl(ctxt, _parserFeatures, _avroParserFeatures,
// return new ApacheAvroParserImpl(ctxt, _parserFeatures, _avroParserFeatures,
_objectCodec, data, offset, len);
}
Overridable factory method that actually instantiates desired
generator.
/**
* Overridable factory method that actually instantiates desired
* generator.
*/
@Override
protected JsonGenerator _createGenerator(Writer out, IOContext ctxt) throws IOException {
return _nonByteTarget();
}
//public BufferRecycler _getBufferRecycler()
@Override
protected Writer _createWriter(OutputStream out, JsonEncoding enc, IOContext ctxt) throws IOException {
return _nonByteTarget();
}
/*
/**********************************************************
/* Internal methods
/**********************************************************
*/
protected AvroGenerator _createGenerator(OutputStream out, IOContext ctxt) throws IOException
{
int feats = _avroGeneratorFeatures;
AvroGenerator gen = new AvroGenerator(ctxt, _generatorFeatures, feats,
_objectCodec, out);
return gen;
}
protected <T> T _nonByteSource() throws IOException {
throw new UnsupportedOperationException("Can not create parser for character-based (not byte-based) source");
}
protected <T> T _nonByteTarget() throws IOException {
throw new UnsupportedOperationException("Can not create generator for character-based (not byte-based) target");
}
}