Reputation: 3344
How it's possible to prevent DTD loading (and validation) in XmlValidatingMessageSelector
if !DOCTYPE
section is present in incoming XML in Spring Integration?
UPDATE
Actually, in our SI config we have this filter config
@Bean
public MessageSelector cageXmlValidator() {
XmlValidatingMessageSelector selector = new XmlValidatingMessageSelector(
new ClassPathResource("/CageMessage.xsd"),
XmlValidatingMessageSelector.SchemaType.XML_SCHEMA);
selector.setThrowExceptionOnRejection(true);
return selector;
}
and use it in our flow in the such way
@Bean
public IntegrationFlow processorFlow(
...
MessageSelector cageXmlValidator,
Unmarshaller cageXmlUnmarshaller,
...) {
return IntegrationFlows
.from(cageInputChannel())
...
.filter(cageXmlValidator)
.transform(new UnmarshallingTransformer(cageXmlUnmarshaller))
...
.channel(cageOutputChannel())
.get();
}
I tried also this XmlValidatingMessageSelector
definition but it doesn't work
@Bean
public MessageSelector cageXmlValidator() throws Exception {
XmlValidatingMessageSelector selector = new XmlValidatingMessageSelector(
new ClassPathResource("/CageMessage.xsd"),
XmlValidatingMessageSelector.SchemaType.XML_SCHEMA);
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
selector.setConverter(new DefaultXmlPayloadConverter(factory));
selector.setThrowExceptionOnRejection(true);
return selector;
}
Upvotes: 1
Views: 94
Reputation: 121542
I have a test-case like:
@Test
public void testValidMessage() throws Exception {
Document doc = XmlTestUtil.getDocumentForString("<!DOCTYPE greeting SYSTEM \"greeting.dtd\"><greeting>hello</greeting>");
GenericMessage<Document> docMessage = new GenericMessage<Document>(doc);
PollableChannel validChannel = ac.getBean("validOutputChannel", PollableChannel.class);
MessageChannel inputChannel = ac.getBean("inputChannelA", MessageChannel.class);
inputChannel.send(docMessage);
assertNotNull(validChannel.receive(100));
}
Pay attention to the !DOCTYPE
declaration in the MXL snippet.
That XmlTestUtil.getDocumentForString()
has this code:
DocumentBuilderFactory builder = DocumentBuilderFactory.newInstance();
builder.setNamespaceAware(true);
builder.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
return builder.newDocumentBuilder().parse(
new InputSource(new StringReader(strDoc)));
The latest load-external-dtd
feature does exactly what I need.
So, what you need in your application is to consider to build Document
for your XML in advance before validation and use those feature for the DocumentBuilderFactory
.
UPDATE
The inserting a customized DefaultXmlPayloadConverter
with an appropriate DocumentBuilderFactory
doesn't have effect for our payload:
validationExceptions = this.xmlValidator.validate(this.converter.convertToSource(message.getPayload()));
Where that convertToSource()
looks like:
public Source convertToSource(Object object) {
Source source = null;
if (object instanceof Source) {
source = (Source) object;
}
else if (object instanceof Document) {
source = new DOMSource((Document) object);
}
else if (object instanceof String) {
source = new StringSource((String) object);
}
else {
throw new MessagingException("unsupported payload type [" + object.getClass().getName() + "]");
}
return source;
}
As you see nobody calls that DocumentBuilderFactory
.
What I suggest you to have a .transform()
upfront .filter(cageXmlValidator)
to transform your payload
to the Document
object with the customized DocumentBuilderFactory
.
Seeing the fact that we can't affect internals of the javax.xml.validation.Validator
, I think that would be good compromise to call convertToDocument()
from the validator and wrap it into DOMSource
. That way, indeed, your DefaultXmlPayloadConverter
would have an effect.
Feel free to raise a JIRA or even consider contribution.
Thank you for pointing that out!
Upvotes: 1