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);