com.fasterxml.jackson.dataformat.javaprop.JavaPropsParser Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jackson-dataformat-properties Show documentation
Show all versions of jackson-dataformat-properties Show documentation
Support for reading and writing content of "Java Properties" style
configuration files as if there was implied nesting structure (by default using dots as separators).
The newest version!
package com.fasterxml.jackson.dataformat.javaprop;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Map;
import java.util.Properties;
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.core.base.ParserMinimalBase;
import com.fasterxml.jackson.core.io.IOContext;
import com.fasterxml.jackson.core.util.ByteArrayBuilder;
import com.fasterxml.jackson.core.util.JacksonFeatureSet;
import com.fasterxml.jackson.dataformat.javaprop.io.JPropReadContext;
import com.fasterxml.jackson.dataformat.javaprop.util.JPropNode;
import com.fasterxml.jackson.dataformat.javaprop.util.JPropNodeBuilder;
public class JavaPropsParser extends ParserMinimalBase
{
protected final static JavaPropsSchema DEFAULT_SCHEMA = new JavaPropsSchema();
/**
* Properties capabilities slightly different from defaults, having
* untyped (text-only) scalars
*
* @since 2.12
*/
protected final static JacksonFeatureSet STREAM_READ_CAPABILITIES =
DEFAULT_READ_CAPABILITIES
.with(StreamReadCapability.UNTYPED_SCALARS)
;
/*
/**********************************************************
/* Configuration
/**********************************************************
*/
/**
* Codec used for data binding when (if) requested.
*/
protected ObjectCodec _objectCodec;
/**
* @since 2.16
*/
protected final IOContext _ioContext;
/**
* Although most massaging is done later, caller may be interested in the
* ultimate source.
*/
protected final Object _inputSource;
/**
* Actual {@link java.util.Properties} (or, actually, any {@link java.util.Map}
* with String keys, values) that were parsed and handed to us
* for further processing.
*/
protected final Map,?> _sourceContent;
/**
* Schema we use for parsing Properties into structure of some kind.
*/
protected JavaPropsSchema _schema = DEFAULT_SCHEMA;
/*
/**********************************************************
/* Parsing state
/**********************************************************
*/
protected JPropReadContext _readContext;
protected boolean _closed;
/*
/**********************************************************
/* Recycled helper objects
/**********************************************************
*/
protected ByteArrayBuilder _byteArrayBuilder;
protected byte[] _binaryValue;
/*
/**********************************************************
/* Life-cycle
/**********************************************************
*/
@Deprecated // since 2.10
public JavaPropsParser(IOContext ctxt, Object inputSource,
int parserFeatures, ObjectCodec codec, Properties sourceProps)
{
this(ctxt, parserFeatures, inputSource, codec, (Map,?>) sourceProps);
}
public JavaPropsParser(IOContext ctxt, int parserFeatures, Object inputSource,
ObjectCodec codec, Map,?> sourceMap)
{
super(parserFeatures, ctxt.streamReadConstraints());
_ioContext = ctxt;
_objectCodec = codec;
_inputSource = inputSource;
_sourceContent = sourceMap;
}
@Override
public Version version() {
return PackageVersion.VERSION;
}
@Override
public void setSchema(FormatSchema schema)
{
if (schema instanceof JavaPropsSchema) {
_schema = (JavaPropsSchema) schema;
} else {
super.setSchema(schema);
}
}
@Override
public JavaPropsSchema getSchema() {
return _schema;
}
// we do not take byte-based input, so base impl would be fine
/*
@Override
public int releaseBuffered(OutputStream out) throws IOException {
return -1;
}
*/
// current implementation delegates to JDK `Properties, so we don't ever
// see the input so:
/*
@Override
public int releaseBuffered(Writer w) throws IOException {
return -1;
}
*/
@Override
public void close() throws IOException {
if (!_closed) {
_ioContext.close();
_closed = true;
_readContext = null;
}
}
@Override
public boolean isClosed() {
return _closed;
}
/*
/**********************************************************
/* Public API overrides
/**********************************************************
*/
@Override
public ObjectCodec getCodec() {
return _objectCodec;
}
@Override
public void setCodec(ObjectCodec c) {
_objectCodec = c;
}
@Override
public Object getInputSource() {
return _inputSource;
}
/*
/**********************************************************
/* Overrides: capability introspection methods
/**********************************************************
*/
@Override
public boolean canUseSchema(FormatSchema schema) {
return schema instanceof JavaPropsSchema;
}
@Override
public boolean requiresCustomCodec() { return false;}
@Override
public boolean canReadObjectId() { return false; }
@Override
public boolean canReadTypeId() { return false; }
@Override
public JacksonFeatureSet getReadCapabilities() {
return STREAM_READ_CAPABILITIES;
}
/*
/**********************************************************
/* Public API, structural
/**********************************************************
*/
@Override
public JsonStreamContext getParsingContext() {
return _readContext;
}
/*
/**********************************************************
/* Main parsing API, traversal
/**********************************************************
*/
@Override
public JsonToken nextToken() throws IOException {
_binaryValue = null;
if (_readContext == null) {
if (_closed) {
return null;
}
_closed = true;
JPropNode root = JPropNodeBuilder.build(_sourceContent, _schema);
_readContext = JPropReadContext.create(root);
// 30-Mar-2016, tatu: For debugging can be useful:
/*
System.err.println("SOURCE: ("+root.getClass().getName()+") <<\n"+new ObjectMapper().writerWithDefaultPrettyPrinter()
.writeValueAsString(root.asRaw()));
System.err.println("\n>>");
*/
}
JsonToken t;
while ((t = _readContext.nextToken()) == null) {
_readContext = _readContext.nextContext();
if (_readContext == null) { // end of content
return _updateTokenToNull();
}
streamReadConstraints().validateNestingDepth(_readContext.getNestingDepth());
}
return _updateToken(t);
}
/*
/**********************************************************
/* Main parsing API, textual values
/**********************************************************
*/
@Override // since 2.17
public String currentName() throws IOException {
if (_readContext == null) {
return null;
}
// [JACKSON-395]: start markers require information from parent
if (_currToken == JsonToken.START_OBJECT || _currToken == JsonToken.START_ARRAY) {
JPropReadContext parent = _readContext.getParent();
if (parent != null) {
return parent.getCurrentName();
}
}
return _readContext.getCurrentName();
}
@Override
public void overrideCurrentName(String name) {
_readContext.overrideCurrentName(name);
}
@Deprecated // since 2.17
@Override
public String getCurrentName() throws IOException {
return currentName();
}
@Override
public String getText() throws IOException {
JsonToken t = _currToken;
if (t == JsonToken.VALUE_STRING) {
return _readContext.getCurrentText();
}
if (t == JsonToken.FIELD_NAME) {
return _readContext.getCurrentName();
}
// shouldn't have non-String scalar values so:
return (t == null) ? null : t.asString();
}
@Override
public boolean hasTextCharacters() {
return false;
}
@Override
public char[] getTextCharacters() throws IOException {
String text = getText();
return (text == null) ? null : text.toCharArray();
}
@Override
public int getTextLength() throws IOException {
String text = getText();
return (text == null) ? 0 : text.length();
}
@Override
public int getTextOffset() throws IOException {
return 0;
}
@Override // since 2.8
public int getText(Writer writer) throws IOException
{
String str = getText();
if (str == null) {
return 0;
}
writer.write(str);
return str.length();
}
@SuppressWarnings("resource")
@Override
public byte[] getBinaryValue(Base64Variant variant) throws IOException
{
if (_binaryValue == null) {
if (_currToken != JsonToken.VALUE_STRING) {
_reportError("Current token ("+_currToken+") not VALUE_STRING, can not access as binary");
}
ByteArrayBuilder builder = _getByteArrayBuilder();
_decodeBase64(getText(), builder, variant);
_binaryValue = builder.toByteArray();
}
return _binaryValue;
}
public ByteArrayBuilder _getByteArrayBuilder()
{
if (_byteArrayBuilder == null) {
_byteArrayBuilder = new ByteArrayBuilder();
} else {
_byteArrayBuilder.reset();
}
return _byteArrayBuilder;
}
/*
/**********************************************************
/* Other accessor overrides
/**********************************************************
*/
@Override
public Object getEmbeddedObject() throws IOException {
return null;
}
@Override // since 2.17
public JsonLocation currentLocation() {
return JsonLocation.NA;
}
@Override // since 2.17
public JsonLocation currentTokenLocation() {
return JsonLocation.NA;
}
@Deprecated // since 2.17
@Override
public JsonLocation getCurrentLocation() { return currentLocation(); }
@Deprecated // since 2.17
@Override
public JsonLocation getTokenLocation() { return currentTokenLocation(); }
/*
/**********************************************************
/* Main parsing API, numeric values
/**********************************************************
*/
@Override
public Number getNumberValue() throws IOException {
return _noNumbers();
}
@Override
public NumberType getNumberType() throws IOException {
return _noNumbers();
}
@Override // added in 2.17
public NumberTypeFP getNumberTypeFP() throws IOException {
return NumberTypeFP.UNKNOWN;
}
@Override
public int getIntValue() throws IOException {
return _noNumbers();
}
@Override
public long getLongValue() throws IOException {
return _noNumbers();
}
@Override
public BigInteger getBigIntegerValue() throws IOException {
return _noNumbers();
}
@Override
public float getFloatValue() throws IOException {
return _noNumbers();
}
@Override
public double getDoubleValue() throws IOException {
return _noNumbers();
}
@Override
public BigDecimal getDecimalValue() throws IOException {
return _noNumbers();
}
/*
/**********************************************************
/* Internal helper methods
/**********************************************************
*/
protected T _noNumbers() throws IOException {
_reportError("Current token ("+_currToken+") not numeric, can not use numeric value accessors");
return null;
}
@Override
protected void _handleEOF() throws JsonParseException {
if ((_readContext != null) && !_readContext.inRoot()) {
_reportInvalidEOF(": expected close marker for "+_readContext.typeDesc(), null);
}
}
}