Skip to content

Commit 97fe9eb

Browse files
committed
Fix #483
1 parent 7cec9d4 commit 97fe9eb

File tree

4 files changed

+56
-14
lines changed

4 files changed

+56
-14
lines changed

release-notes/VERSION-2.x

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Project: jackson-dataformat-xml
1717
#474: Empty String ("") parsed as 0 for int even if
1818
DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES enabled (note:
1919
actual fix in `jackson-databind)
20+
#483: Explicitly pass ClassLoader of XmlFactory when creating Stax input/output factory,
21+
instead of context ClassLoader
2022
- Rename `XmlFactoryBuilder` methods "inputFactory()"->"xmlInputFactory()",
2123
"outputFactory()" -> "xmlOutputFactory()"
2224
- Woodstox dependency 6.2.6 (from 6.2.4)

src/main/java/com/fasterxml/jackson/dataformat/xml/XmlFactory.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,14 +111,18 @@ protected XmlFactory(ObjectCodec oc, int xpFeatures, int xgFeatures,
111111
_xmlGeneratorFeatures = xgFeatures;
112112
_cfgNameForTextElement = nameForTextElem;
113113
if (xmlIn == null) {
114-
xmlIn = XMLInputFactory.newInstance();
114+
// 05-Jul-2021, tatu: as per [dataformat-xml#483], specify ClassLoader
115+
xmlIn = XMLInputFactory.newFactory(XMLInputFactory.class.getName(),
116+
getClass().getClassLoader());
115117
// as per [dataformat-xml#190], disable external entity expansion by default
116118
xmlIn.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
117119
// and ditto wrt [dataformat-xml#211], SUPPORT_DTD
118120
xmlIn.setProperty(XMLInputFactory.SUPPORT_DTD, Boolean.FALSE);
119121
}
120122
if (xmlOut == null) {
121-
xmlOut = XMLOutputFactory.newInstance();
123+
// 05-Jul-2021, tatu: as per [dataformat-xml#483], specify ClassLoader
124+
xmlOut = XMLOutputFactory.newFactory(XMLOutputFactory.class.getName(),
125+
getClass().getClassLoader());
122126
}
123127
_initFactories(xmlIn, xmlOut);
124128
_xmlInputFactory = xmlIn;

src/main/java/com/fasterxml/jackson/dataformat/xml/XmlFactoryBuilder.java

Lines changed: 47 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,8 @@
88
import com.fasterxml.jackson.dataformat.xml.ser.ToXmlGenerator;
99

1010
/**
11-
* {@link com.fasterxml.jackson.core.TSFBuilder}
12-
* implementation for constructing {@link XmlFactory}
13-
* instances.
14-
*
15-
* @since 3.0
11+
* {@link com.fasterxml.jackson.core.TSFBuilder} implementation
12+
* for constructing {@link XmlFactory} instances.
1613
*/
1714
public class XmlFactoryBuilder extends TSFBuilder<XmlFactory, XmlFactoryBuilder>
1815
{
@@ -51,11 +48,21 @@ public class XmlFactoryBuilder extends TSFBuilder<XmlFactory, XmlFactoryBuilder>
5148
*<p>
5249
* Name used for pseudo-property used for returning XML Text value (which does
5350
* not have actual element name to use). Defaults to empty String, but
54-
* may be changed for inter-operability reasons: JAXB, for example, uses
51+
* may be changed for interoperability reasons: JAXB, for example, uses
5552
* "value" as name.
5653
*/
5754
protected String _nameForTextElement;
5855

56+
/**
57+
* Optional {@link ClassLoader} to use for constructing
58+
* {@link XMLInputFactory} and {@kink XMLOutputFactory} instances if
59+
* not explicitly specified by caller. If not specified, will
60+
* default to {@link ClassLoader} that loaded this class.
61+
*
62+
* @since 2.13
63+
*/
64+
protected ClassLoader _classLoaderForStax;
65+
5966
/*
6067
/**********************************************************
6168
/* Life cycle
@@ -65,6 +72,7 @@ public class XmlFactoryBuilder extends TSFBuilder<XmlFactory, XmlFactoryBuilder>
6572
protected XmlFactoryBuilder() {
6673
_formatParserFeatures = XmlFactory.DEFAULT_XML_PARSER_FEATURE_FLAGS;
6774
_formatGeneratorFeatures = XmlFactory.DEFAULT_XML_GENERATOR_FEATURE_FLAGS;
75+
_classLoaderForStax = null;
6876
}
6977

7078
public XmlFactoryBuilder(XmlFactory base) {
@@ -74,6 +82,7 @@ public XmlFactoryBuilder(XmlFactory base) {
7482
_xmlInputFactory = base._xmlInputFactory;
7583
_xmlOutputFactory = base._xmlOutputFactory;
7684
_nameForTextElement = base._cfgNameForTextElement;
85+
_classLoaderForStax = null;
7786
}
7887

7988
// // // Accessors
@@ -90,8 +99,11 @@ public XMLInputFactory xmlInputFactory() {
9099
return _xmlInputFactory;
91100
}
92101

93-
protected static XMLInputFactory defaultInputFactory() {
94-
XMLInputFactory xmlIn = XMLInputFactory.newInstance();
102+
protected XMLInputFactory defaultInputFactory() {
103+
// 05-Jul-2021, tatu: as per [dataformat-xml#483], consider ClassLoader
104+
XMLInputFactory xmlIn = XMLInputFactory.newFactory(XMLInputFactory.class.getName(),
105+
staxClassLoader());
106+
95107
// as per [dataformat-xml#190], disable external entity expansion by default
96108
xmlIn.setProperty(XMLInputFactory.IS_SUPPORTING_EXTERNAL_ENTITIES, Boolean.FALSE);
97109
// and ditto wrt [dataformat-xml#211], SUPPORT_DTD
@@ -106,13 +118,21 @@ public XMLOutputFactory xmlOutputFactory() {
106118
return _xmlOutputFactory;
107119
}
108120

109-
protected static XMLOutputFactory defaultOutputFactory() {
110-
XMLOutputFactory xmlOut = XMLOutputFactory.newInstance();
121+
protected XMLOutputFactory defaultOutputFactory() {
122+
// 05-Jul-2021, tatu: as per [dataformat-xml#483], consider ClassLoader
123+
XMLOutputFactory xmlOut = XMLOutputFactory.newFactory(XMLOutputFactory.class.getName(),
124+
staxClassLoader());
111125
// [dataformat-xml#326]: Better ensure namespaces get built properly:
112126
xmlOut.setProperty(XMLOutputFactory.IS_REPAIRING_NAMESPACES, Boolean.TRUE);
113127
return xmlOut;
114128
}
115129

130+
// @since 2.13
131+
protected ClassLoader staxClassLoader() {
132+
return (_classLoaderForStax == null) ?
133+
getClass().getClassLoader() : _classLoaderForStax;
134+
}
135+
116136
// // // Parser features
117137

118138
public XmlFactoryBuilder enable(FromXmlParser.Feature f) {
@@ -217,11 +237,27 @@ public XmlFactoryBuilder outputFactory(XMLOutputFactory xmlOut) {
217237
return xmlOutputFactory(xmlOut);
218238
}
219239

240+
/**
241+
* Method that can be used to specific {@link ClassLoader} for creating
242+
* {@link XMLInputFactory} and {@link XMLOutputFactory} instances if
243+
* those are not explicitly defined by caller: passed to respective
244+
* {@code newFactory()} methods.
245+
*<br>
246+
* NOTE: recommended approach is to explicitly pass {@link XMLInputFactory}
247+
* and {@link XMLOutputFactory} methods instead of relying on JDK SPI
248+
* mechanism.
249+
*
250+
* @since 2.13
251+
*/
252+
public XmlFactoryBuilder staxClassLoader(ClassLoader cl) {
253+
_classLoaderForStax = cl;
254+
return _this();
255+
}
256+
220257
// // // Actual construction
221258

222259
@Override
223260
public XmlFactory build() {
224-
// 28-Dec-2017, tatu: No special settings beyond base class ones, so:
225261
return new XmlFactory(this);
226262
}
227263
}

src/test/java/com/fasterxml/jackson/dataformat/xml/failing/UnwrappedAndList299DeserTest.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ public void testXmlMarshallingAndUnmarshalling() throws Exception {
5353
assertEquals(request.composite.number, anotherRequest.composite.number);
5454

5555
assertEquals("ABC", anotherRequest.composite.messageId);
56-
assertEquals(new Integer(123), anotherRequest.composite.number);
56+
assertEquals(Integer.valueOf(123), anotherRequest.composite.number);
5757
assertEquals(2, anotherRequest.composite.headers.size());
5858
assertEquals("headerID1", anotherRequest.composite.headers.get(0).headerId);
5959
assertEquals("headerID2", anotherRequest.composite.headers.get(1).headerId);

0 commit comments

Comments
 (0)