From 2345b4e3cc1ceda6bb35472b953b90ac6ceee665 Mon Sep 17 00:00:00 2001 From: facundov Date: Thu, 2 Nov 2017 10:42:57 -0300 Subject: [PATCH] MULE-13487: In unmarshaller, make errorLimitCounter customizable. --- .../unmarshaller/UnmarshallerImpl.java | 11 ++ .../unmarshaller/UnmarshallerProperties.java | 6 ++ .../unmarshaller/UnmarshallingContext.java | 38 +++++-- .../java/com/sun/xml/bind/utils/Person.java | 9 ++ .../runtime/unmarshaller/LimitErrorTest.java | 100 ++++++++++++++++++ 5 files changed, 153 insertions(+), 11 deletions(-) create mode 100644 jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallerProperties.java create mode 100644 jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/utils/Person.java create mode 100644 jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/runtime/unmarshaller/LimitErrorTest.java diff --git a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallerImpl.java b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallerImpl.java index f38440c60..f93d0b49f 100644 --- a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallerImpl.java +++ b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallerImpl.java @@ -40,6 +40,9 @@ package com.sun.xml.bind.v2.runtime.unmarshaller; +import static com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerProperties.ENABLE_ERROR_REPORT_LIMIT; +import static com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerProperties.ERROR_REPORT_LIMIT; + import java.io.IOException; import java.io.InputStream; @@ -511,6 +514,14 @@ public void setProperty(String name, Object value) throws PropertyException { coordinator.classLoader = (ClassLoader)value; return; } + if(name.equals(ENABLE_ERROR_REPORT_LIMIT)) { + coordinator.setLimitErrorReporting((boolean) value); + return ; + } + if(name.equals(ERROR_REPORT_LIMIT)) { + coordinator.setErrorsCounter((int)value); + return ; + } super.setProperty(name, value); } diff --git a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallerProperties.java b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallerProperties.java new file mode 100644 index 000000000..ae10bd644 --- /dev/null +++ b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallerProperties.java @@ -0,0 +1,6 @@ +package com.sun.xml.bind.v2.runtime.unmarshaller; + +public class UnmarshallerProperties { + public static final String ENABLE_ERROR_REPORT_LIMIT = "unmarshaller.enableErrorReportLimit"; + public static final String ERROR_REPORT_LIMIT = "unmarshaller.errorReportLimit"; +} diff --git a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallingContext.java b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallingContext.java index a8af3cb8f..b077a25b3 100644 --- a/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallingContext.java +++ b/jaxb-ri/runtime/impl/src/main/java/com/sun/xml/bind/v2/runtime/unmarshaller/UnmarshallingContext.java @@ -68,7 +68,6 @@ import com.sun.istack.Nullable; import com.sun.istack.SAXParseException2; import com.sun.xml.bind.IDResolver; -import com.sun.xml.bind.Util; import com.sun.xml.bind.api.AccessorException; import com.sun.xml.bind.api.ClassResolver; import com.sun.xml.bind.unmarshaller.InfosetScanner; @@ -77,8 +76,6 @@ import com.sun.xml.bind.v2.runtime.Coordinator; import com.sun.xml.bind.v2.runtime.JAXBContextImpl; import com.sun.xml.bind.v2.runtime.JaxBeanInfo; -import java.util.logging.Level; -import java.util.logging.Logger; import org.xml.sax.ErrorHandler; import org.xml.sax.Locator; @@ -199,13 +196,24 @@ public final class UnmarshallingContext extends Coordinator */ public @Nullable ClassLoader classLoader; + public static volatile int DEFAULT_ERROR_COUNTER = 10; + /** - * The variable introduced to avoid reporting n^10 similar errors. - * After error is reported counter is decremented. When it became 0 - errors should not be reported any more. + * The variable introduced to avoid reporting more than {@value DEFAULT_ERROR_COUNTER} errors. + * The default value can be overrode setting the {@link UnmarshallerProperties#ERROR_REPORT_LIMIT} property in the {@link Unmarshaller}. + * After error is reported counter is decremented. When it became lower than 0, errors should not be reported any more. + * If the {@link UnmarshallingContext#limitErrorReporting} is set to false, this field will be totally ignored. * * volatile is required to ensure that concurrent threads will see changed value */ - private static volatile int errorsCounter = 10; + private volatile int errorsCounter = DEFAULT_ERROR_COUNTER; + + /** + * Indicates if it should exist an error reporting limit. Default value is true. + * This property can be overrode setting the setting the {@link UnmarshallerProperties#ENABLE_ERROR_REPORT_LIMIT} property in the {@link Unmarshaller}. + * + */ + private volatile boolean limitErrorReporting = true; /** * State information for each element. @@ -1336,8 +1344,16 @@ public StructureLoader getStructureLoader() { return null; } + public void setErrorsCounter(int errorsCounter) { + this.errorsCounter = errorsCounter; + } + + public void setLimitErrorReporting(boolean limitErrorReporting) { + this.limitErrorReporting = limitErrorReporting; + } + /** - * Based on current {@link Logger} {@link Level} and errorCounter value determines if error should be reported. + * Based on current {@link UnmarshallingContext#limitErrorReporting} and errorCounter value determines if error should be reported. * * If the method called and return true it is expected that error will be reported. And that's why * errorCounter is automatically decremented during the check. @@ -1345,19 +1361,19 @@ public StructureLoader getStructureLoader() { * NOT THREAD SAFE!!! In case of heave concurrency access several additional errors could be reported. It's not expected to be the * problem. Otherwise add synchronization here. * - * @return true in case if {@link Level#FINEST} is set OR we haven't exceed errors reporting limit. + * @return true in case if {@link UnmarshallingContext#limitErrorReporting} OR we haven't exceed errors reporting limit. */ public boolean shouldErrorBeReported() throws SAXException { - if (logger.isLoggable(Level.FINEST)) + if (!limitErrorReporting) return true; if (errorsCounter >= 0) { --errorsCounter; - if (errorsCounter == 0) // it's possible to miss this because of concurrency. If required add synchronization here + if (errorsCounter == -1) // it's possible to miss this because of concurrency. If required add synchronization here handleEvent(new ValidationEventImpl(ValidationEvent.WARNING, Messages.ERRORS_LIMIT_EXCEEDED.format(), getLocator().getLocation(), null), true); } - return errorsCounter >= 0; + return false; } } diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/utils/Person.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/utils/Person.java new file mode 100644 index 000000000..e4c999b7d --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/utils/Person.java @@ -0,0 +1,9 @@ +package com.sun.xml.bind.utils; + +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement +public class Person { + + private String value; +} diff --git a/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/runtime/unmarshaller/LimitErrorTest.java b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/runtime/unmarshaller/LimitErrorTest.java new file mode 100644 index 000000000..15741591c --- /dev/null +++ b/jaxb-ri/runtime/impl/src/test/java/com/sun/xml/bind/v2/runtime/unmarshaller/LimitErrorTest.java @@ -0,0 +1,100 @@ +package com.sun.xml.bind.v2.runtime.unmarshaller; + +import static com.sun.xml.bind.v2.runtime.unmarshaller.Messages.ERRORS_LIMIT_EXCEEDED; +import static com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallerProperties.ENABLE_ERROR_REPORT_LIMIT; +import static com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.DEFAULT_ERROR_COUNTER; +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; + +import com.sun.xml.bind.utils.Person; + +import java.io.ByteArrayInputStream; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Unmarshaller; +import javax.xml.bind.ValidationEvent; +import javax.xml.bind.util.ValidationEventCollector; + +import junit.framework.TestCase; + + +public class LimitErrorTest extends TestCase { + + private static final String EXPECTED_ERROR_MESSAGE = "unexpected element (uri:\"\", local:\"unexpectedChild\"). Expected elements are (none)"; + private static final String GENERIC_ERROR_MESSAGE = ERRORS_LIMIT_EXCEEDED.format(); + private final ValidationEventCollector validationCollector = new JAXB2ValidationEventCollector(); + private static final String xml = "" + + "" + + "" + + ""; + + private Unmarshaller unmarshaller = null; + + protected void setUp() throws Exception { + unmarshaller = JAXBContext.newInstance(Person.class).createUnmarshaller(); + unmarshaller.setEventHandler(validationCollector); + } + + public void testDisableErrorReportLimit() throws Exception + { + unmarshaller.setProperty(ENABLE_ERROR_REPORT_LIMIT, false); + + for (int i = 0; i < DEFAULT_ERROR_COUNTER + 1; i ++) { + try { + unmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes())); + } + catch (JAXBException e) { + assertThat(e.getMessage(), is(EXPECTED_ERROR_MESSAGE)); + } + } + } + + public void testEnableErrorReportLimit() { + + for (int i = 0; i < DEFAULT_ERROR_COUNTER; i ++) { + try { + unmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes())); + } + catch (JAXBException e) { + assertThat(e.getMessage(), is(EXPECTED_ERROR_MESSAGE)); + } + } + + try { + unmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes())); + } + catch (JAXBException e) { + assertThat(e.getMessage(), is(GENERIC_ERROR_MESSAGE)); + } + } + + public void testCustomErrorReportLimit() { + int customErrorReportLimit = 5; + for (int i = 0; i < customErrorReportLimit; i ++) { + try { + unmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes())); + } + catch (JAXBException e) { + assertThat(e.getMessage(), is(EXPECTED_ERROR_MESSAGE)); + } + } + + try { + unmarshaller.unmarshal(new ByteArrayInputStream(xml.getBytes())); + } + catch (JAXBException e) { + assertThat(e.getMessage(), is(GENERIC_ERROR_MESSAGE)); + } + } + + + private class JAXB2ValidationEventCollector extends ValidationEventCollector { + @Override + public boolean handleEvent(ValidationEvent event) { + super.handleEvent(event); + return false; + } + } + +} \ No newline at end of file