diff --git a/src/main/java/com/fasterxml/jackson/core/JsonFactory.java b/src/main/java/com/fasterxml/jackson/core/JsonFactory.java index 489fc86ef2..cd19f2019b 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonFactory.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonFactory.java @@ -1987,7 +1987,7 @@ protected IOContext _createNonBlockingContext(Object srcRef) { protected ContentReference _createContentReference(Object contentAccessor) { // 21-Mar-2021, tatu: For now assume "canHandleBinaryNatively()" is reliable // indicator of textual vs binary format: - return new ContentReference(!canHandleBinaryNatively(), contentAccessor); + return ContentReference.construct(!canHandleBinaryNatively(), contentAccessor); } /** @@ -2010,7 +2010,7 @@ protected ContentReference _createContentReference(Object contentAccessor, { // 21-Mar-2021, tatu: For now assume "canHandleBinaryNatively()" is reliable // indicator of textual vs binary format: - return new ContentReference(!canHandleBinaryNatively(), + return ContentReference.construct(!canHandleBinaryNatively(), contentAccessor, offset, length); } diff --git a/src/main/java/com/fasterxml/jackson/core/JsonLocation.java b/src/main/java/com/fasterxml/jackson/core/JsonLocation.java index f6265d816e..8b1c05eb53 100644 --- a/src/main/java/com/fasterxml/jackson/core/JsonLocation.java +++ b/src/main/java/com/fasterxml/jackson/core/JsonLocation.java @@ -87,7 +87,7 @@ protected static ContentReference _wrap(Object srcRef) { if (srcRef instanceof ContentReference) { return (ContentReference) srcRef; } - return new ContentReference(false, srcRef); + return ContentReference.construct(false, srcRef); } /** @@ -234,29 +234,35 @@ protected StringBuilder _appendSourceDesc(StringBuilder sb) tn = "char[]"; } sb.append('(').append(tn).append(')'); - // and then, include (part of) contents for selected types: - int len; - String charStr = " chars"; - if (srcRef instanceof CharSequence) { - CharSequence cs = (CharSequence) srcRef; - len = cs.length(); - len -= _append(sb, cs.subSequence(0, Math.min(len, MAX_CONTENT_SNIPPET)).toString()); - } else if (srcRef instanceof char[]) { - char[] ch = (char[]) srcRef; - len = ch.length; - len -= _append(sb, new String(ch, 0, Math.min(len, MAX_CONTENT_SNIPPET))); - } else if (srcRef instanceof byte[]) { - byte[] b = (byte[]) srcRef; - int maxLen = Math.min(b.length, MAX_CONTENT_SNIPPET); - _append(sb, new String(b, 0, maxLen, Charset.forName("UTF-8"))); - len = b.length - maxLen; - charStr = " bytes"; + // and then, include (part of) contents for selected types + // (never for binary-format data) + if (_contentReference.hasTextualContent()) { + int len; + String charStr = " chars"; + + if (srcRef instanceof CharSequence) { + CharSequence cs = (CharSequence) srcRef; + len = cs.length(); + len -= _append(sb, cs.subSequence(0, Math.min(len, MAX_CONTENT_SNIPPET)).toString()); + } else if (srcRef instanceof char[]) { + char[] ch = (char[]) srcRef; + len = ch.length; + len -= _append(sb, new String(ch, 0, Math.min(len, MAX_CONTENT_SNIPPET))); + } else if (srcRef instanceof byte[]) { + byte[] b = (byte[]) srcRef; + int maxLen = Math.min(b.length, MAX_CONTENT_SNIPPET); + _append(sb, new String(b, 0, maxLen, Charset.forName("UTF-8"))); + len = b.length - maxLen; + charStr = " bytes"; + } else { + len = 0; + } + if (len > 0) { + sb.append("[truncated ").append(len).append(charStr).append(']'); + } } else { - len = 0; - } - if (len > 0) { - sb.append("[truncated ").append(len).append(charStr).append(']'); + } return sb; } diff --git a/src/main/java/com/fasterxml/jackson/core/io/ContentReference.java b/src/main/java/com/fasterxml/jackson/core/io/ContentReference.java index ecccddaa3e..a6b98e3dc3 100644 --- a/src/main/java/com/fasterxml/jackson/core/io/ContentReference.java +++ b/src/main/java/com/fasterxml/jackson/core/io/ContentReference.java @@ -59,11 +59,11 @@ public class ContentReference /********************************************************************** */ - public ContentReference(boolean isContentTextual, Object rawContent) { + protected ContentReference(boolean isContentTextual, Object rawContent) { this(isContentTextual, rawContent, -1, -1); } - public ContentReference(boolean isContentTextual, Object rawContent, + protected ContentReference(boolean isContentTextual, Object rawContent, int offset, int length) { _isContentTextual = isContentTextual; @@ -83,6 +83,15 @@ public static ContentReference unknown() { return UNKNOWN_CONTENT; } + public static ContentReference construct(boolean isContentTextual, Object rawContent) { + return new ContentReference(isContentTextual, rawContent); + } + + public static ContentReference construct(boolean isContentTextual, Object rawContent, + int offset, int length) { + return new ContentReference(isContentTextual, rawContent, offset, length); + } + /** * Factory method for legacy code to use for constructing instances to * content about which only minimal amount of information is available. @@ -91,10 +100,10 @@ public static ContentReference unknown() { * @param rawContent Underlying raw content access * * @return Instance with minimal information about content (basically just - * raw content reference without offsets; + * raw content reference without offsets */ public static ContentReference rawReference(Object rawContent) { - // 14-Mar-2021, tatu: Just to avoid russian-doll-nesting, let's: + // Just to avoid russian-doll-nesting, let's: if (rawContent instanceof ContentReference) { return (ContentReference) rawContent; } @@ -136,6 +145,9 @@ public Object getRawContent() { return _rawContent; } + public int contentOffset() { return _offset; } + public int contentLength() { return _length; } + /* /********************************************************************** /* Standard method overrides diff --git a/src/test/java/com/fasterxml/jackson/core/TestJDKSerializability.java b/src/test/java/com/fasterxml/jackson/core/TestJDKSerializability.java index f59d834c48..af3b88a4b9 100644 --- a/src/test/java/com/fasterxml/jackson/core/TestJDKSerializability.java +++ b/src/test/java/com/fasterxml/jackson/core/TestJDKSerializability.java @@ -84,7 +84,7 @@ public void testLocation() throws Exception public void testSourceReference() throws Exception { - ContentReference ref = new ContentReference(true, "text"); + ContentReference ref = ContentReference.construct(true, "text"); byte[] stuff = jdkSerialize(ref); ContentReference ref2 = jdkDeserialize(stuff); diff --git a/src/test/java/com/fasterxml/jackson/core/TestLocation.java b/src/test/java/com/fasterxml/jackson/core/TestLocation.java index 4dafcddfda..a6f328f6b9 100644 --- a/src/test/java/com/fasterxml/jackson/core/TestLocation.java +++ b/src/test/java/com/fasterxml/jackson/core/TestLocation.java @@ -50,12 +50,12 @@ public void testBasicToString() throws Exception // Class that specifies source type assertEquals("[Source: (InputStream); line: 1, column: 2]", - new JsonLocation(_sourceRef(InputStream.class), 10L, 10L, 1, 2).toString()); + new JsonLocation(_rawSourceRef(InputStream.class), 10L, 10L, 1, 2).toString()); // misc other Foobar srcRef = new Foobar(); assertEquals("[Source: ("+srcRef.getClass().getName()+"); line: 1, column: 2]", - new JsonLocation(_sourceRef(srcRef), 10L, 10L, 1, 2).toString()); + new JsonLocation(_rawSourceRef(srcRef), 10L, 10L, 1, 2).toString()); } public void testTruncatedSource() throws Exception @@ -111,7 +111,23 @@ public void testDisableSourceInclusion() throws Exception p.close(); } - private ContentReference _sourceRef(Object rawSrc) { + private ContentReference _sourceRef(String rawSrc) { + return ContentReference.construct(true, rawSrc, 0, rawSrc.length()); + } + + private ContentReference _sourceRef(char[] rawSrc) { + return ContentReference.construct(true, rawSrc, 0, rawSrc.length); + } + + private ContentReference _sourceRef(byte[] rawSrc) { + return ContentReference.construct(true, rawSrc, 0, rawSrc.length); + } + + private ContentReference _sourceRef(InputStream rawSrc) { + return ContentReference.construct(true, rawSrc, -1, -1); + } + + private ContentReference _rawSourceRef(Object rawSrc) { return ContentReference.rawReference(rawSrc); } }