Skip to content

Commit 38af89b

Browse files
committed
Fix FasterXML#311 by wrapping IonExceptions in IonParser
1 parent b082f58 commit 38af89b

File tree

2 files changed

+141
-9
lines changed

2 files changed

+141
-9
lines changed

ion/src/main/java/com/fasterxml/jackson/dataformat/ion/IonParser.java

+31-6
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,13 @@
2121

2222
import com.fasterxml.jackson.core.*;
2323
import com.fasterxml.jackson.core.base.ParserMinimalBase;
24+
import com.fasterxml.jackson.core.io.ContentReference;
2425
import com.fasterxml.jackson.core.io.IOContext;
2526
import com.fasterxml.jackson.core.json.JsonReadContext;
2627
import com.fasterxml.jackson.core.util.JacksonFeatureSet;
2728
import com.amazon.ion.*;
2829
import com.amazon.ion.system.IonSystemBuilder;
30+
import org.w3c.dom.Text;
2931

3032
/**
3133
* Implementation of {@link JsonParser} that will use an underlying
@@ -265,7 +267,13 @@ public String getText() throws IOException
265267
case FIELD_NAME:
266268
return getCurrentName();
267269
case VALUE_STRING:
268-
return _reader.stringValue();
270+
try {
271+
// stringValue() will throw an UnknownSymbolException if we're
272+
// trying to get the text for a symbol id that cannot be resolved.
273+
return _reader.stringValue();
274+
} catch (UnknownSymbolException e) {
275+
throw _constructError(e.getMessage(), e);
276+
}
269277
case VALUE_NUMBER_INT:
270278
case VALUE_NUMBER_FLOAT:
271279
Number n = getNumberValue();
@@ -512,7 +520,12 @@ public JsonToken nextToken() throws IOException
512520
}
513521

514522
// any more tokens in this scope?
515-
IonType type = _reader.next();
523+
IonType type = null;
524+
try {
525+
type = _reader.next();
526+
} catch (IonException e) {
527+
_wrapError(e.getMessage(), e);
528+
}
516529
if (type == null) {
517530
if (_parsingContext.inRoot()) { // EOF?
518531
close();
@@ -528,7 +541,13 @@ public JsonToken nextToken() throws IOException
528541
boolean inStruct = !_parsingContext.inRoot() && _reader.isInStruct();
529542
// (isInStruct can return true for the first value read if the reader
530543
// was created from an IonValue that has a parent container)
531-
_parsingContext.setCurrentName(inStruct ? _reader.getFieldName() : null);
544+
try {
545+
// getFieldName() can throw an UnknownSymbolException if the text of the
546+
// field name symbol cannot be resolved.
547+
_parsingContext.setCurrentName(inStruct ? _reader.getFieldName() : null);
548+
} catch (UnknownSymbolException e) {
549+
_wrapError(e.getMessage(), e);
550+
}
532551
JsonToken t = _tokenFromType(type);
533552
// and return either field name first
534553
if (inStruct) {
@@ -542,9 +561,15 @@ public JsonToken nextToken() throws IOException
542561
/**
543562
* @see com.fasterxml.jackson.dataformat.ion.polymorphism.IonAnnotationTypeDeserializer
544563
*/
545-
public String[] getTypeAnnotations() {
546-
// Per its spec, will not return null
547-
return _reader.getTypeAnnotations();
564+
public String[] getTypeAnnotations() throws JsonParseException {
565+
try {
566+
// Per its spec, will not return null
567+
return _reader.getTypeAnnotations();
568+
} catch (UnknownSymbolException e) {
569+
// IonReader.getTypeAnnotations() can throw an UnknownSymbolException if the text of any
570+
// the annotation symbols cannot be resolved.
571+
throw _constructError(e.getMessage(), e);
572+
}
548573
}
549574

550575
@Override

ion/src/test/java/com/fasterxml/jackson/dataformat/ion/IonParserTest.java

+110-3
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,7 @@
1414

1515
package com.fasterxml.jackson.dataformat.ion;
1616

17-
import com.fasterxml.jackson.core.JsonParser;
18-
import com.fasterxml.jackson.core.JsonToken;
19-
import com.fasterxml.jackson.core.StreamReadCapability;
17+
import com.fasterxml.jackson.core.*;
2018

2119
import org.junit.Assert;
2220

@@ -28,8 +26,12 @@
2826
import java.io.IOException;
2927
import java.math.BigDecimal;
3028
import java.math.BigInteger;
29+
import java.util.List;
30+
3131
import org.junit.Test;
3232

33+
import static org.junit.Assert.assertEquals;
34+
3335
@SuppressWarnings("resource")
3436
public class IonParserTest
3537
{
@@ -125,4 +127,109 @@ public void testParserCapabilities() throws Exception {
125127
}
126128
}
127129

130+
131+
@Test(expected = JsonParseException.class)
132+
public void testIonExceptionIsWrapped() throws IOException
133+
{
134+
IonFactory f = new IonFactory();
135+
try (IonParser parser = (IonParser) f.createParser("[ 12, true ) ]")) {
136+
assertEquals(JsonToken.START_ARRAY, parser.nextToken());
137+
assertEquals(JsonToken.VALUE_NUMBER_INT, parser.nextValue());
138+
assertEquals(12, parser.getIntValue());
139+
assertEquals(JsonToken.VALUE_TRUE, parser.nextValue());
140+
parser.nextValue();
141+
}
142+
}
143+
144+
@Test(expected = JsonParseException.class)
145+
public void testUnknownSymbolExceptionForValueIsWrapped() throws IOException
146+
{
147+
IonFactory f = new IonFactory();
148+
try (IonParser parser = (IonParser) f.createParser("[ 12, $99 ]")) {
149+
assertEquals(JsonToken.START_ARRAY, parser.nextToken());
150+
assertEquals(JsonToken.VALUE_NUMBER_INT, parser.nextValue());
151+
assertEquals(12, parser.getIntValue());
152+
assertEquals(JsonToken.VALUE_STRING, parser.nextValue());
153+
parser.getValueAsString(); // Should encounter unknown symbol and fail
154+
}
155+
}
156+
157+
@Test(expected = JsonParseException.class)
158+
public void testUnknownSymbolExceptionForFieldNameIsWrapped() throws IOException
159+
{
160+
IonFactory f = new IonFactory();
161+
try (IonParser parser = (IonParser) f.createParser("{ a: 1, $99: 2 }")) {
162+
assertEquals(JsonToken.START_OBJECT, parser.nextToken());
163+
assertEquals(JsonToken.FIELD_NAME, parser.nextToken());
164+
assertEquals("a", parser.getCurrentName());
165+
assertEquals(JsonToken.VALUE_NUMBER_INT, parser.nextValue());
166+
assertEquals(1, parser.getIntValue());
167+
parser.nextValue(); // Should encounter unknown symbol and fail
168+
}
169+
}
170+
171+
@Test(expected = JsonParseException.class)
172+
public void testUnknownSymbolExceptionForAnnotationIsWrapped() throws IOException
173+
{
174+
IonFactory f = new IonFactory();
175+
try (IonParser parser = (IonParser) f.createParser("{ a: $99::1 }")) {
176+
assertEquals(JsonToken.START_OBJECT, parser.nextToken());
177+
assertEquals(JsonToken.FIELD_NAME, parser.nextToken());
178+
assertEquals("a", parser.getCurrentName());
179+
assertEquals(JsonToken.VALUE_NUMBER_INT, parser.nextValue());
180+
assertEquals(1, parser.getIntValue());
181+
parser.getTypeAnnotations(); // Should encounter unknown symbol and fail
182+
}
183+
}
184+
185+
static class FooBar {
186+
public int foo;
187+
public List<Object> bar;
188+
}
189+
190+
191+
public static class IonExceptionTests {
192+
IonObjectMapper mapper = new IonObjectMapper();
193+
194+
// throws JsonMapperException, depends on IonParser.nextToken()
195+
// mapper.reader().readValue("{ foo: \"boo\", bar: (1 null.string 2e0 3d0 { ) }", FooBar.class)
196+
197+
// throws JsonMapperException, depends on IonParser.nextToken(), IonObjectMapper._readMapAndClose()
198+
// mapper.readValue("{ foo: \"boo\", bar: (1 null.string 2e0 3d0 { ) }", FooBar.class)
199+
200+
201+
// FooBar fb = mapper.readValue("{ foo: 1, bar: ( ] ) }", FooBar.class);
202+
// FooBar fb = mapper.readValue("{ foo: 1, bar: ( ] ) }", FooBar.class);
203+
204+
205+
@Test(expected = JacksonException.class)
206+
public void testIonObjectMapper1() throws IOException {
207+
mapper.readValue("{ foo: 1, bar: ( ] ) }", FooBar.class);
208+
}
209+
210+
@Test(expected = JacksonException.class)
211+
public void testIonObjectMapper2() throws IOException {
212+
mapper.readValue("{ foo: 1, bar: (1 null.string 2e0 3d0 { ) }", FooBar.class);
213+
}
214+
215+
@Test(expected = JacksonException.class)
216+
public void testIonObjectMapper3() throws IOException {
217+
mapper.readValue("{ foo: 1, bar: ( ) ] }", FooBar.class);
218+
}
219+
220+
@Test(expected = JacksonException.class)
221+
public void testIonObjectMapper4() throws IOException {
222+
mapper.reader().readValue("{ foo: 1, bar: ( ] ) }", FooBar.class);
223+
}
224+
225+
@Test(expected = JacksonException.class)
226+
public void testIonObjectMapper5() throws IOException {
227+
mapper.reader().readValue("{ foo: 1, bar: (1 null.string 2e0 3d0 { ) }", FooBar.class);
228+
}
229+
230+
@Test(expected = JacksonException.class)
231+
public void testIonObjectMapper6() throws IOException {
232+
mapper.reader().readValue("{ foo: 1, bar: ( ) ] }", FooBar.class);
233+
}
234+
}
128235
}

0 commit comments

Comments
 (0)