Skip to content

Commit 39c98a0

Browse files
committed
[CXF-8966] : fix validation of nil int in xsd
1 parent fce94b8 commit 39c98a0

File tree

5 files changed

+158
-44
lines changed

5 files changed

+158
-44
lines changed

core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataReader.java

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import javax.xml.namespace.QName;
2929
import javax.xml.stream.XMLStreamException;
3030
import javax.xml.stream.XMLStreamReader;
31-
import javax.xml.stream.XMLStreamWriter;
3231
import javax.xml.transform.Source;
3332
import javax.xml.transform.dom.DOMSource;
3433
import javax.xml.transform.sax.SAXSource;
@@ -216,33 +215,37 @@ public void close() throws XMLStreamException {
216215
}
217216

218217
private Element validate(XMLStreamReader input) throws XMLStreamException, IOException {
219-
DOMSource ds = read(input);
220-
final Element rootElement;
221-
if (ds.getNode() instanceof Document) {
222-
rootElement = ((Document)ds.getNode()).getDocumentElement();
223-
} else {
224-
rootElement = (Element)ds.getNode();
225-
}
226-
218+
Element rootElement;
227219
WoodstoxValidationImpl impl = new WoodstoxValidationImpl();
228-
XMLStreamWriter nullWriter = null;
220+
XMLStreamReader inputWithoutXop = null;
229221
if (impl.canValidate()) {
230-
nullWriter = StaxUtils.createXMLStreamWriter(new NUllOutputStream());
231-
impl.setupValidation(nullWriter, message.getExchange().getEndpoint(),
232-
message.getExchange().getService().getServiceInfos().get(0));
222+
//filter xop node, which causes validation to fail
223+
XMLStreamReader filteredReader =
224+
StaxUtils.createFilteredReader(input, new StaxStreamFilter(XOP));
225+
try (CachedOutputStream out = new CachedOutputStream()) {
226+
StaxUtils.copy(filteredReader, out);
227+
inputWithoutXop = StaxUtils.createXMLStreamReader(out.getInputStream());
228+
impl.setupValidation(inputWithoutXop, message.getExchange().getEndpoint(),
229+
message.getExchange().getService().getServiceInfos().get(0));
230+
} finally {
231+
filteredReader.close();
232+
}
233233
}
234234
//check if the impl can still validate after the setup, possible issue loading schemas or similar
235235
if (impl.canValidate()) {
236236
//Can use the MSV libs and woodstox to handle the schema validation during
237-
//parsing and processing. Much faster and single traversal
238-
//filter xop node
239-
XMLStreamReader reader = StaxUtils.createXMLStreamReader(ds);
240-
XMLStreamReader filteredReader =
241-
StaxUtils.createFilteredReader(reader,
242-
new StaxStreamFilter(new QName[] {XOP}));
237+
//parsing and processing. Much faster and single traversal
238+
rootElement = StaxUtils.read(inputWithoutXop).getDocumentElement();
243239

244-
StaxUtils.copy(filteredReader, nullWriter);
245240
} else {
241+
242+
DOMSource ds = read(input);
243+
if (ds.getNode() instanceof Document) {
244+
rootElement = ((Document)ds.getNode()).getDocumentElement();
245+
} else {
246+
rootElement = (Element)ds.getNode();
247+
}
248+
246249
//MSV not available, use a slower method of cloning the data, replace the xop's, validate
247250
LOG.fine("NO_MSV_AVAILABLE");
248251
Element newElement = rootElement;
@@ -314,14 +317,4 @@ public void setProperty(String prop, Object value) {
314317
message = (Message)value;
315318
}
316319
}
317-
318-
static class NUllOutputStream extends OutputStream {
319-
public void write(byte[] b, int off, int len) {
320-
}
321-
public void write(int b) {
322-
}
323-
324-
public void write(byte[] b) throws IOException {
325-
}
326-
}
327320
}

core/src/test/java/org/apache/cxf/databinding/source/XMLStreamDataReaderTest.java

Lines changed: 112 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,27 +22,79 @@
2222
import java.io.ByteArrayInputStream;
2323
import java.io.IOException;
2424
import java.io.InputStream;
25+
import java.net.URL;
2526

27+
import javax.xml.XMLConstants;
2628
import javax.xml.namespace.QName;
29+
import javax.xml.parsers.DocumentBuilder;
30+
import javax.xml.parsers.DocumentBuilderFactory;
31+
import javax.xml.stream.XMLInputFactory;
2732
import javax.xml.stream.XMLStreamReader;
33+
import javax.xml.transform.dom.DOMSource;
34+
import javax.xml.validation.Schema;
35+
import javax.xml.validation.SchemaFactory;
2836

37+
import org.w3c.dom.Document;
38+
39+
import com.ctc.wstx.msv.W3CSchemaFactory;
40+
41+
import org.apache.cxf.endpoint.Endpoint;
2942
import org.apache.cxf.interceptor.Fault;
43+
import org.apache.cxf.message.Exchange;
44+
import org.apache.cxf.message.ExchangeImpl;
3045
import org.apache.cxf.message.Message;
3146
import org.apache.cxf.message.MessageImpl;
47+
import org.apache.cxf.service.Service;
48+
import org.apache.cxf.service.ServiceImpl;
49+
import org.apache.cxf.service.model.MessageInfo;
50+
import org.apache.cxf.service.model.MessagePartInfo;
51+
import org.apache.cxf.service.model.ServiceInfo;
3252
import org.apache.cxf.staxutils.StaxUtils;
53+
import org.codehaus.stax2.XMLStreamReader2;
54+
import org.codehaus.stax2.validation.XMLValidationSchema;
3355

3456
import org.junit.Test;
3557

58+
import static org.junit.Assert.assertEquals;
3659
import static org.junit.Assert.assertFalse;
3760
import static org.junit.Assert.assertTrue;
61+
import static org.junit.Assert.fail;
62+
import static org.mockito.Mockito.mock;
63+
import static org.mockito.Mockito.when;
3864

3965
/**
4066
*
4167
*/
4268
public class XMLStreamDataReaderTest {
4369
private static final byte[] DUMMY_DATA = "<ns:dummy xmlns:ns='http://www.apache.org/cxf'/>".getBytes();
4470
private static final byte[] DUMMY_DATA_NULL_BYTE =
45-
"<ns:dummy xmlns:ns='http://www.apache.org/cxf&#x00;'/>".getBytes();
71+
"<ns:dummy xmlns:ns='http://www.apache.org/cxf&#x00;'/>".getBytes();
72+
73+
// Parse some XML with a null byte and check we don't return internal Woodstox package names in the error message
74+
@Test
75+
public void testParseNullByte() throws Exception {
76+
XMLStreamDataReader reader = new XMLStreamDataReader();
77+
Message msg = new MessageImpl();
78+
79+
TestInputStream in1 = new TestInputStream(DUMMY_DATA_NULL_BYTE);
80+
81+
msg.setContent(InputStream.class, in1);
82+
83+
reader.setProperty(Message.class.getName(), msg);
84+
85+
Object obj = reader.read(new QName("http://www.apache.org/cxf", "dummy"),
86+
StaxUtils.createXMLStreamReader(in1), XMLStreamReader.class);
87+
88+
assertTrue(obj instanceof XMLStreamReader);
89+
90+
try {
91+
reader.read((XMLStreamReader) obj);
92+
} catch (Fault f) {
93+
assertFalse(f.getMessage().contains("com.ctc.wstx"));
94+
}
95+
96+
((XMLStreamReader)obj).close();
97+
}
4698

4799
@Test
48100
public void testCloseOriginalInputStream() throws Exception {
@@ -66,30 +118,76 @@ public void testCloseOriginalInputStream() throws Exception {
66118
assertTrue(in1.isClosed());
67119
}
68120

69-
// Parse some XML with a null byte and check we don't return internal Woodstox package names in the error message
70121
@Test
71-
public void testParseNullByte() throws Exception {
122+
public void testValid() throws Exception {
123+
testValidate("resources/schema.xsd", "resources/test-valid.xml", false);
124+
}
125+
126+
@Test
127+
public void testInValid() throws Exception {
128+
testValidate("resources/schema.xsd", "resources/test-invalid.xml", true);
129+
}
130+
131+
132+
private void testValidate(String schemaPath, String xmlPath, boolean exceptionExpected) throws Exception {
133+
134+
//create schema
135+
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
136+
documentBuilderFactory.setNamespaceAware(true);
137+
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
138+
URL schemaURI = getClass().getResource(schemaPath);
139+
Document wsdl = documentBuilder.parse(schemaURI.openStream());
140+
String wsdlSystemId = schemaURI.toExternalForm();
141+
DOMSource source = new DOMSource(wsdl);
142+
source.setSystemId(wsdlSystemId);
143+
source.setSystemId(wsdlSystemId);
144+
145+
XMLValidationSchema schemaw3c =
146+
W3CSchemaFactory.newInstance(XMLValidationSchema.SCHEMA_ID_W3C_SCHEMA).createSchema(schemaURI);
147+
SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
148+
Schema schema = schemaFactory.newSchema(schemaURI);
149+
72150
XMLStreamDataReader reader = new XMLStreamDataReader();
151+
reader.setSchema(schema);
152+
153+
154+
InputStream testIS = getClass().getResourceAsStream(xmlPath);
73155
Message msg = new MessageImpl();
156+
Exchange exchange = new ExchangeImpl();
74157

75-
TestInputStream in1 = new TestInputStream(DUMMY_DATA_NULL_BYTE);
158+
ServiceInfo serviceInfo = new ServiceInfo();
76159

77-
msg.setContent(InputStream.class, in1);
160+
Endpoint endpoint = mock(Endpoint.class);
161+
when(endpoint.get(XMLValidationSchema.class.getName())).thenReturn(schemaw3c);
78162

79-
reader.setProperty(Message.class.getName(), msg);
163+
Service svc = new ServiceImpl(serviceInfo);
80164

81-
Object obj = reader.read(new QName("http://www.apache.org/cxf", "dummy"),
82-
StaxUtils.createXMLStreamReader(in1), XMLStreamReader.class);
165+
exchange.put(Service.class, svc);
166+
exchange.put(Endpoint.class, endpoint);
83167

84-
assertTrue(obj instanceof XMLStreamReader);
168+
msg.setExchange(exchange);
169+
msg.setContent(InputStream.class, testIS);
170+
reader.setProperty(Message.class.getName(), msg);
85171

172+
XMLInputFactory xmlFactory = XMLInputFactory.newInstance();
173+
XMLStreamReader2 xmlStreamReader = (XMLStreamReader2) xmlFactory.createXMLStreamReader(testIS, "utf-8");
174+
175+
MessageInfo messageInfo = new MessageInfo(null,
176+
MessageInfo.Type.INPUT,
177+
new QName("http://www.test.org/services",
178+
"NullTestOperationRequest"));
179+
MessagePartInfo messagePartInfo = new MessagePartInfo(new QName(
180+
"http://www.test.org/services", "NullTestOperationRequest"), messageInfo);
181+
messagePartInfo.setElement(true);
182+
boolean exceptionCaught = false;
86183
try {
87-
reader.read((XMLStreamReader) obj);
88-
} catch (Fault f) {
89-
assertFalse(f.getMessage().contains("com.ctc.wstx"));
184+
reader.read(messagePartInfo, xmlStreamReader);
185+
} catch (Fault fault) {
186+
exceptionCaught = true;
187+
} catch (Exception exc) {
188+
fail(exc.getMessage());
90189
}
91-
92-
((XMLStreamReader)obj).close();
190+
assertEquals(exceptionExpected, exceptionCaught);
93191
}
94192

95193
private static class TestInputStream extends ByteArrayInputStream {
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.test.org/service/">
2+
<xsd:element name="NullTestOperationRequest" nillable="true">
3+
<xsd:complexType>
4+
<xsd:sequence>
5+
<xsd:element nillable="true" name="inInt" type="xsd:int" maxOccurs="1" minOccurs="0" ></xsd:element>
6+
<xsd:element nillable="true" name="inInteger" type="xsd:integer" maxOccurs="1" minOccurs="0" ></xsd:element>
7+
<xsd:element nillable="true" name="inString" type="xsd:string" maxOccurs="1" minOccurs="0" ></xsd:element>
8+
</xsd:sequence>
9+
</xsd:complexType>
10+
</xsd:element>
11+
</xsd:schema>
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<ser:NullTestOperationRequest xmlns:ser="http://www.test.org/service/">
2+
3+
<inInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="false"/>
4+
5+
</ser:NullTestOperationRequest>
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<ser:NullTestOperationRequest xmlns:ser="http://www.test.org/service/">
2+
3+
<inInt xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
4+
<inInteger xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
5+
<inString xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nil="true"/>
6+
7+
</ser:NullTestOperationRequest>

0 commit comments

Comments
 (0)