diff --git a/src/main/java/org/apache/xmlbeans/impl/richParser/XMLStreamReaderExtImpl.java b/src/main/java/org/apache/xmlbeans/impl/richParser/XMLStreamReaderExtImpl.java index c015a3f0b..a6ce66a1e 100644 --- a/src/main/java/org/apache/xmlbeans/impl/richParser/XMLStreamReaderExtImpl.java +++ b/src/main/java/org/apache/xmlbeans/impl/richParser/XMLStreamReaderExtImpl.java @@ -205,7 +205,7 @@ public Date getDateValue() _charSeq.reload(CharSeqTrimWS.XMLWHITESPACE_TRIM); try { return new GDateBuilder(_charSeq).getDate(); - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException | IllegalStateException e) { throw new InvalidLexicalValueException(e, _charSeq.getLocation()); } } @@ -353,7 +353,7 @@ public Date getAttributeDateValue(int index) throws XMLStreamException { try { return new GDateBuilder(_charSeq.reloadAtt(index, CharSeqTrimWS.XMLWHITESPACE_TRIM)) .getDate(); - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException | IllegalStateException e) { throw new InvalidLexicalValueException(e, _charSeq.getLocation()); } } @@ -507,7 +507,7 @@ public Date getAttributeDateValue(String uri, String local) throws XMLStreamExce try { CharSequence cs = _charSeq.reloadAtt(uri, local, CharSeqTrimWS.XMLWHITESPACE_TRIM); return new GDateBuilder(cs).getDate(); - } catch (IllegalArgumentException e) { + } catch (IllegalArgumentException | IllegalStateException e) { throw new InvalidLexicalValueException(e, _charSeq.getLocation()); } } diff --git a/src/test/java/misc/checkin/RichParserTests.java b/src/test/java/misc/checkin/RichParserTests.java index 1c74de7b1..6c57203ea 100755 --- a/src/test/java/misc/checkin/RichParserTests.java +++ b/src/test/java/misc/checkin/RichParserTests.java @@ -107,6 +107,35 @@ void testInvalidQNameThrowsInvalidLexicalValue() throws Exception { assertEquals(new QName("urn:x", "good"), good.getQNameValue()); } + @Test + void testInvalidDateThrowsInvalidLexicalValue() throws Exception { + // getDateValue converts the parsed GDate to a java.util.Date via + // GDateBuilder.getDate(), which throws IllegalStateException - not + // IllegalArgumentException - when the value is not a complete date + // (a time/gYear/gYearMonth reaching a dateTime field) or its year is + // before the Julian epoch. The getter only caught IllegalArgumentException + // so the IllegalStateException escaped instead of the documented + // InvalidLexicalValueException the other getters surface. + XMLStreamReaderExt timeOnly = atFirstStartElement("12:00:00"); + assertThrows(InvalidLexicalValueException.class, timeOnly::getDateValue); + + XMLStreamReaderExt yearOnly = atFirstStartElement("2001"); + assertThrows(InvalidLexicalValueException.class, yearOnly::getDateValue); + + XMLStreamReaderExt ancient = atFirstStartElement("-5000-01-01T00:00:00Z"); + assertThrows(InvalidLexicalValueException.class, ancient::getDateValue); + + XMLStreamReaderExt attByIndex = atFirstStartElement(""); + assertThrows(InvalidLexicalValueException.class, () -> attByIndex.getAttributeDateValue(0)); + + XMLStreamReaderExt attByName = atFirstStartElement(""); + assertThrows(InvalidLexicalValueException.class, () -> attByName.getAttributeDateValue("", "b")); + + // a well-formed dateTime still converts + XMLStreamReaderExt good = atFirstStartElement("2001-11-26T21:32:52Z"); + assertEquals(new XmlCalendar("2001-11-26T21:32:52Z").getTime(), good.getDateValue()); + } + private static XMLStreamReaderExt atFirstStartElement(String xml) throws Exception { XMLStreamReader xsr = XmlObject.Factory.parse(xml).newXMLStreamReader(); XMLStreamReaderExt ext = new XMLStreamReaderExtImpl(xsr);