Skip to content

Commit b720140

Browse files
committed
Allow XML components injection
**Cherry-pick to 5.0.x & 4.3.x** * Polishing after rebase * Copyright to 2019 * Rebase and update according upstream deps * Do not rely on `spring-web` in classpath: use `ClassUtils.forName()` to load `ServletContextResource` class for checking # Conflicts: # build.gradle # spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/XmlValidatingMessageSelector.java # spring-integration-xml/src/main/java/org/springframework/integration/xml/transformer/XsltPayloadTransformer.java # spring-integration-xml/src/main/java/org/springframework/integration/xml/xpath/XPathUtils.java # spring-integration-xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTests.java # Conflicts: # build.gradle # spring-integration-xml/src/main/java/org/springframework/integration/xml/DefaultXmlPayloadConverter.java # spring-integration-xml/src/main/java/org/springframework/integration/xml/splitter/XPathMessageSplitter.java # spring-integration-xml/src/test/java/org/springframework/integration/xml/transformer/XsltPayloadTransformerTests.java
1 parent a2d419e commit b720140

File tree

17 files changed

+391
-196
lines changed

17 files changed

+391
-196
lines changed

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ subprojects { subproject ->
138138
springSocialTwitterVersion = '1.1.2.RELEASE'
139139
springRetryVersion = '1.1.3.RELEASE'
140140
springVersion = project.hasProperty('springVersion') ? project.springVersion : '4.3.22.RELEASE'
141-
springWsVersion = '2.3.0.RELEASE'
141+
springWsVersion = '2.4.4.RELEASE'
142142
xmlUnitVersion = '1.6'
143143
xstreamVersion = '1.4.7'
144144
}

spring-integration-xml/src/main/java/org/springframework/integration/xml/DefaultXmlPayloadConverter.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -33,6 +33,8 @@
3333
import org.xml.sax.InputSource;
3434

3535
import org.springframework.messaging.MessagingException;
36+
import org.springframework.util.Assert;
37+
import org.springframework.xml.DocumentBuilderFactoryUtils;
3638
import org.springframework.xml.transform.StringSource;
3739

3840
/**
@@ -49,11 +51,12 @@ public class DefaultXmlPayloadConverter implements XmlPayloadConverter {
4951

5052

5153
public DefaultXmlPayloadConverter() {
52-
this.documentBuilderFactory = DocumentBuilderFactory.newInstance();
54+
this(DocumentBuilderFactoryUtils.newInstance());
5355
this.documentBuilderFactory.setNamespaceAware(true);
5456
}
5557

5658
public DefaultXmlPayloadConverter(DocumentBuilderFactory documentBuilderFactory) {
59+
Assert.notNull(documentBuilderFactory, "'documentBuilderFactory' must not be null.");
5760
this.documentBuilderFactory = documentBuilderFactory;
5861
}
5962

@@ -116,7 +119,7 @@ protected Document nodeToDocument(Node node) {
116119

117120
@Override
118121
public Node convertToNode(Object object) {
119-
Node node = null;
122+
Node node;
120123
if (object instanceof Node) {
121124
node = (Node) object;
122125
}
@@ -131,7 +134,7 @@ else if (object instanceof DOMSource) {
131134

132135
@Override
133136
public Source convertToSource(Object object) {
134-
Source source = null;
137+
Source source;
135138
if (object instanceof Source) {
136139
source = (Source) object;
137140
}

spring-integration-xml/src/main/java/org/springframework/integration/xml/config/XPathHeaderEnricherParser.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2014 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -34,6 +34,7 @@
3434
*
3535
* @author Mark Fisher
3636
* @author Artem Bilan
37+
*
3738
* @since 2.0
3839
*/
3940
public class XPathHeaderEnricherParser extends AbstractTransformerParser {
@@ -46,14 +47,15 @@ protected final String getTransformerClassName() {
4647
@Override
4748
protected void parseTransformer(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
4849
ManagedMap<String, Object> headers = new ManagedMap<String, Object>();
49-
this.processHeaders(element, headers, parserContext);
50+
processHeaders(element, headers, parserContext);
5051
builder.addConstructorArgValue(headers);
5152
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "default-overwrite");
5253
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "should-skip-nulls");
5354
}
5455

5556
protected void processHeaders(Element element, ManagedMap<String, Object> headers, ParserContext parserContext) {
5657
Object source = parserContext.extractSource(element);
58+
String converter = element.getAttribute("converter");
5759
NodeList childNodes = element.getChildNodes();
5860
for (int i = 0; i < childNodes.getLength(); i++) {
5961
Node node = childNodes.item(i);
@@ -62,21 +64,26 @@ protected void processHeaders(Element element, ManagedMap<String, Object> header
6264
String elementName = node.getLocalName();
6365
if ("header".equals(elementName)) {
6466
BeanDefinitionBuilder builder =
65-
BeanDefinitionBuilder.genericBeanDefinition(XPathExpressionEvaluatingHeaderValueMessageProcessor.class);
67+
BeanDefinitionBuilder.genericBeanDefinition(
68+
XPathExpressionEvaluatingHeaderValueMessageProcessor.class);
6669
String expressionString = headerElement.getAttribute("xpath-expression");
6770
String expressionRef = headerElement.getAttribute("xpath-expression-ref");
6871
boolean isExpressionString = StringUtils.hasText(expressionString);
6972
boolean isExpressionRef = StringUtils.hasText(expressionRef);
70-
if (!(isExpressionString ^ isExpressionRef)) {
73+
if (isExpressionString == isExpressionRef) {
7174
parserContext.getReaderContext().error(
72-
"Exactly one of the 'xpath-expression' or 'xpath-expression-ref' attributes is required.", source);
75+
"Exactly one of the 'xpath-expression' " +
76+
"or 'xpath-expression-ref' attributes is required.", source);
7377
}
7478
if (isExpressionString) {
7579
builder.addConstructorArgValue(expressionString);
7680
}
7781
else {
7882
builder.addConstructorArgReference(expressionRef);
7983
}
84+
if (StringUtils.hasText(converter)) {
85+
builder.addConstructorArgReference(converter);
86+
}
8087
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, headerElement, "evaluation-type");
8188
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, headerElement, "overwrite");
8289
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, headerElement, "header-type");

spring-integration-xml/src/main/java/org/springframework/integration/xml/result/DomResultFactory.java

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2010 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -23,23 +23,26 @@
2323
import javax.xml.transform.dom.DOMResult;
2424

2525
import org.springframework.messaging.MessagingException;
26+
import org.springframework.util.Assert;
27+
import org.springframework.xml.DocumentBuilderFactoryUtils;
2628

2729
/**
2830
* @author Jonas Partner
31+
* @author Artem Bilan
2932
*/
3033
public class DomResultFactory implements ResultFactory {
3134

3235
private final DocumentBuilderFactory documentBuilderFactory;
3336

3437

35-
public DomResultFactory(DocumentBuilderFactory documentBuilderFactory) {
36-
this.documentBuilderFactory = documentBuilderFactory;
38+
public DomResultFactory() {
39+
this(DocumentBuilderFactoryUtils.newInstance());
40+
this.documentBuilderFactory.setNamespaceAware(true);
3741
}
3842

39-
public DomResultFactory() {
40-
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
41-
factory.setNamespaceAware(true);
42-
this.documentBuilderFactory = factory;
43+
public DomResultFactory(DocumentBuilderFactory documentBuilderFactory) {
44+
Assert.notNull(documentBuilderFactory, "'documentBuilderFactory' must not be null.");
45+
this.documentBuilderFactory = documentBuilderFactory;
4346
}
4447

4548

spring-integration-xml/src/main/java/org/springframework/integration/xml/selector/XmlValidatingMessageSelector.java

Lines changed: 25 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121

2222
import org.apache.commons.logging.Log;
2323
import org.apache.commons.logging.LogFactory;
24-
import org.xml.sax.SAXParseException;
2524

2625
import org.springframework.core.io.Resource;
2726
import org.springframework.integration.MessageRejectedException;
@@ -41,6 +40,8 @@
4140
* @author Oleg Zhurakousky
4241
* @author Gary Russell
4342
* @author Liujiong
43+
* @author Artem Bilan
44+
*
4445
* @since 2.0
4546
*/
4647
public class XmlValidatingMessageSelector implements MessageSelector {
@@ -63,43 +64,42 @@ public String getUrl() {
6364

6465
}
6566

66-
private final Log logger = LogFactory.getLog(this.getClass());
67+
private final Log logger = LogFactory.getLog(getClass());
6768

6869
private final XmlValidator xmlValidator;
6970

70-
private volatile boolean throwExceptionOnRejection;
71+
private boolean throwExceptionOnRejection;
7172

72-
private volatile XmlPayloadConverter converter = new DefaultXmlPayloadConverter();
73-
74-
75-
public XmlValidatingMessageSelector(XmlValidator xmlValidator) {
76-
Assert.notNull(xmlValidator, "XmlValidator must not be null");
77-
this.xmlValidator = xmlValidator;
78-
}
73+
private XmlPayloadConverter converter = new DefaultXmlPayloadConverter();
7974

8075

8176
/**
8277
* Creates a selector with a default {@link XmlValidator}. The validator will be initialized with
8378
* the provided 'schema' location {@link Resource} and 'schemaType'. The valid options for schema
8479
* type are {@link XmlValidatorFactory#SCHEMA_W3C_XML} or {@link XmlValidatorFactory#SCHEMA_RELAX_NG}.
8580
* If no 'schemaType' is provided it will default to {@link XmlValidatorFactory#SCHEMA_W3C_XML};
86-
*
8781
* @param schema The schema.
8882
* @param schemaType The schema type.
89-
*
9083
* @throws IOException if the XmlValidatorFactory fails to create a validator
9184
*/
9285
public XmlValidatingMessageSelector(Resource schema, SchemaType schemaType) throws IOException {
93-
Assert.notNull(schema, "You must provide XML schema location to perform validation");
94-
if (schemaType == null) {
95-
schemaType = SchemaType.XML_SCHEMA;
96-
}
97-
this.xmlValidator = XmlValidatorFactory.createValidator(schema, schemaType.getUrl());
86+
this(XmlValidatorFactory.createValidator(schema,
87+
schemaType == null
88+
? SchemaType.XML_SCHEMA.getUrl()
89+
: schemaType.getUrl()));
90+
}
91+
92+
public XmlValidatingMessageSelector(XmlValidator xmlValidator) {
93+
Assert.notNull(xmlValidator, "XmlValidator must not be null");
94+
this.xmlValidator = xmlValidator;
9895
}
9996

97+
10098
public XmlValidatingMessageSelector(Resource schema, String schemaType) throws IOException {
101-
this(schema, StringUtils.isEmpty(schemaType) ? null :
102-
SchemaType.valueOf(schemaType.toUpperCase().replaceFirst("-", "_")));
99+
this(schema,
100+
StringUtils.isEmpty(schemaType)
101+
? null
102+
: SchemaType.valueOf(schemaType.toUpperCase().replaceFirst("-", "_")));
103103
}
104104

105105

@@ -119,7 +119,7 @@ public void setConverter(XmlPayloadConverter converter) {
119119

120120
@Override
121121
public boolean accept(Message<?> message) {
122-
SAXParseException[] validationExceptions = null;
122+
Throwable[] validationExceptions = null;
123123
try {
124124
validationExceptions = this.xmlValidator.validate(this.converter.convertToSource(message.getPayload()));
125125
}
@@ -130,10 +130,12 @@ public boolean accept(Message<?> message) {
130130
if (!validationSuccess) {
131131
if (this.throwExceptionOnRejection) {
132132
throw new MessageRejectedException(message, "Message was rejected due to XML Validation errors",
133-
new AggregatedXmlMessageValidationException(
134-
Arrays.<Throwable>asList(validationExceptions)));
133+
new AggregatedXmlMessageValidationException(Arrays.asList(validationExceptions)));
134+
}
135+
else if (this.logger.isInfoEnabled()) {
136+
this.logger.info("Message was rejected due to XML Validation errors",
137+
new AggregatedXmlMessageValidationException(Arrays.asList(validationExceptions)));
135138
}
136-
this.logger.debug("Message was rejected due to XML Validation errors");
137139
}
138140
return validationSuccess;
139141
}

spring-integration-xml/src/main/java/org/springframework/integration/xml/source/DomSourceFactory.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,26 +29,29 @@
2929
import org.xml.sax.InputSource;
3030

3131
import org.springframework.messaging.MessagingException;
32+
import org.springframework.util.Assert;
33+
import org.springframework.xml.DocumentBuilderFactoryUtils;
3234

3335
/**
3436
* {@link SourceFactory} implementation which supports creation of a {@link DOMSource}
3537
* from a {@link Document}, {@link File} or {@link String} payload.
3638
*
3739
* @author Jonas Partner
3840
* @author Mark Fisher
41+
* @author Artem Bilan
3942
*/
4043
public class DomSourceFactory implements SourceFactory {
4144

4245
private final DocumentBuilderFactory documentBuilderFactory;
4346

4447

4548
public DomSourceFactory() {
46-
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
47-
factory.setNamespaceAware(true);
48-
this.documentBuilderFactory = factory;
49+
this(DocumentBuilderFactoryUtils.newInstance());
50+
this.documentBuilderFactory.setNamespaceAware(true);
4951
}
5052

5153
public DomSourceFactory(DocumentBuilderFactory documentBuilderFactory) {
54+
Assert.notNull(documentBuilderFactory, "'documentBuilderFactory' must not be null.");
5255
this.documentBuilderFactory = documentBuilderFactory;
5356
}
5457

@@ -87,7 +90,7 @@ private DOMSource createDomSourceForString(String s) {
8790

8891
private DOMSource createDomSourceForFile(File file) {
8992
try {
90-
Document document = this.getNewDocumentBuilder().parse(file);
93+
Document document = getNewDocumentBuilder().parse(file);
9194
return new DOMSource(document.getDocumentElement());
9295
}
9396
catch (Exception e) {

spring-integration-xml/src/main/java/org/springframework/integration/xml/source/StringSourceFactory.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2016 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,27 +27,31 @@
2727
import org.w3c.dom.Document;
2828

2929
import org.springframework.messaging.MessagingException;
30+
import org.springframework.util.Assert;
3031
import org.springframework.util.FileCopyUtils;
3132
import org.springframework.xml.transform.StringResult;
3233
import org.springframework.xml.transform.StringSource;
34+
import org.springframework.xml.transform.TransformerFactoryUtils;
3335

3436
/**
3537
* {@link SourceFactory} implementation which supports creation of a {@link StringSource}
3638
* from a {@link Document}, {@link File} or {@link String} payload
3739
*
3840
* @author Jonas Partner
3941
* @author Mark Fisher
42+
* @author Artem Bilan
4043
*/
4144
public class StringSourceFactory implements SourceFactory {
4245

4346
private final TransformerFactory transformerFactory;
4447

4548

4649
public StringSourceFactory() {
47-
this(TransformerFactory.newInstance());
50+
this(TransformerFactoryUtils.newInstance());
4851
}
4952

5053
public StringSourceFactory(TransformerFactory transformerFactory) {
54+
Assert.notNull(transformerFactory, "'transformerFactory' must not be null.");
5155
this.transformerFactory = transformerFactory;
5256
}
5357

0 commit comments

Comments
 (0)