/* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.oxm.castor; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.StringReader; import java.util.concurrent.atomic.AtomicReference; import javax.xml.transform.sax.SAXSource; import javax.xml.transform.stream.StreamSource; import org.junit.Ignore; import org.junit.Test; import org.springframework.core.io.ClassPathResource; import org.springframework.oxm.AbstractUnmarshallerTests; import org.springframework.oxm.MarshallingException; import org.xml.sax.InputSource; import org.xml.sax.XMLReader; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; /** * @author Arjen Poutsma * @author Jakub Narloch * @author Sam Brannen */ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests<CastorMarshaller> { /** * Represents the xml with additional attribute that is not mapped in Castor config. */ protected static final String EXTRA_ATTRIBUTES_STRING = "<tns:flights xmlns:tns=\"http://samples.springframework.org/flight\">" + "<tns:flight status=\"canceled\"><tns:number>42</tns:number></tns:flight></tns:flights>"; /** * Represents the xml with additional element that is not mapped in Castor config. */ protected static final String EXTRA_ELEMENTS_STRING = "<tns:flights xmlns:tns=\"http://samples.springframework.org/flight\">" + "<tns:flight><tns:number>42</tns:number><tns:date>2011-06-14</tns:date>" + "</tns:flight></tns:flights>"; @Override protected CastorMarshaller createUnmarshaller() throws Exception { CastorMarshaller marshaller = new CastorMarshaller(); ClassPathResource mappingLocation = new ClassPathResource("mapping.xml", CastorMarshaller.class); marshaller.setMappingLocation(mappingLocation); marshaller.afterPropertiesSet(); return marshaller; } @Override protected void testFlights(Object o) { Flights flights = (Flights) o; assertNotNull("Flights is null", flights); assertEquals("Invalid amount of flight elements", 1, flights.getFlightCount()); testFlight(flights.getFlight()[0]); } @Override protected void testFlight(Object o) { Flight flight = (Flight) o; assertNotNull("Flight is null", flight); assertThat("Number is invalid", flight.getNumber(), equalTo(42L)); } @Test public void unmarshalTargetClass() throws Exception { CastorMarshaller unmarshaller = new CastorMarshaller(); unmarshaller.setTargetClasses(new Class[] {Flights.class}); unmarshaller.afterPropertiesSet(); StreamSource source = new StreamSource(new ByteArrayInputStream(INPUT_STRING.getBytes("UTF-8"))); Object flights = unmarshaller.unmarshal(source); testFlights(flights); } @Test public void setBothTargetClassesAndMapping() throws IOException { CastorMarshaller unmarshaller = new CastorMarshaller(); unmarshaller.setMappingLocation(new ClassPathResource("order-mapping.xml", CastorMarshaller.class)); unmarshaller.setTargetClasses(new Class[] {Order.class}); unmarshaller.afterPropertiesSet(); String xml = "<order>" + "<order-item id=\"1\" quantity=\"15\"/>" + "<order-item id=\"3\" quantity=\"20\"/>" + "</order>"; Order order = (Order) unmarshaller.unmarshal(new StreamSource(new StringReader(xml))); assertEquals("Invalid amount of items", 2, order.getOrderItemCount()); OrderItem item = order.getOrderItem(0); assertEquals("Invalid items", "1", item.getId()); assertThat("Invalid items", item.getQuantity(), equalTo(15)); item = order.getOrderItem(1); assertEquals("Invalid items", "3", item.getId()); assertThat("Invalid items", item.getQuantity(), equalTo(20)); } @Test public void whitespacePreserveTrue() throws Exception { unmarshaller.setWhitespacePreserve(true); Object result = unmarshalFlights(); testFlights(result); } @Test public void whitespacePreserveFalse() throws Exception { unmarshaller.setWhitespacePreserve(false); Object result = unmarshalFlights(); testFlights(result); } @Test public void ignoreExtraAttributesTrue() throws Exception { unmarshaller.setIgnoreExtraAttributes(true); Object result = unmarshal(EXTRA_ATTRIBUTES_STRING); testFlights(result); } @Test(expected = MarshallingException.class) public void ignoreExtraAttributesFalse() throws Exception { unmarshaller.setIgnoreExtraAttributes(false); unmarshal(EXTRA_ATTRIBUTES_STRING); } @Test @Ignore("Not working yet") public void ignoreExtraElementsTrue() throws Exception { unmarshaller.setIgnoreExtraElements(true); unmarshaller.setValidating(false); Object result = unmarshal(EXTRA_ELEMENTS_STRING); testFlights(result); } @Test(expected = MarshallingException.class) public void ignoreExtraElementsFalse() throws Exception { unmarshaller.setIgnoreExtraElements(false); unmarshal(EXTRA_ELEMENTS_STRING); } @Test public void rootObject() throws Exception { Flights flights = new Flights(); unmarshaller.setRootObject(flights); Object result = unmarshalFlights(); testFlights(result); assertSame("Result Flights is different object.", flights, result); } @Test public void clearCollectionsTrue() throws Exception { Flights flights = new Flights(); flights.setFlight(new Flight[]{new Flight()}); unmarshaller.setRootObject(flights); unmarshaller.setClearCollections(true); Object result = unmarshalFlights(); assertSame("Result Flights is different object.", flights, result); assertEquals("Result Flights has incorrect number of Flight.", 1, ((Flights) result).getFlightCount()); testFlights(result); } @Test @Ignore("Fails on the build server for some reason") public void clearCollectionsFalse() throws Exception { Flights flights = new Flights(); flights.setFlight(new Flight[] {new Flight(), null}); unmarshaller.setRootObject(flights); unmarshaller.setClearCollections(false); Object result = unmarshalFlights(); assertSame("Result Flights is different object.", flights, result); assertEquals("Result Flights has incorrect number of Flight.", 3, ((Flights) result).getFlightCount()); assertNull("Flight shouldn't have number.", flights.getFlight(0).getNumber()); assertNull("Null Flight was expected.", flights.getFlight()[1]); testFlight(flights.getFlight()[2]); } @Test public void unmarshalStreamSourceWithXmlOptions() throws Exception { final AtomicReference<XMLReader> result = new AtomicReference<>(); CastorMarshaller marshaller = new CastorMarshaller() { @Override protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource) { result.set(xmlReader); return null; } }; // 1. external-general-entities and dtd support disabled (default) marshaller.unmarshal(new StreamSource("1")); assertNotNull(result.get()); assertEquals(true, result.get().getFeature("http://apache.org/xml/features/disallow-doctype-decl")); assertEquals(false, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); // 2. external-general-entities and dtd support enabled result.set(null); marshaller.setSupportDtd(true); marshaller.setProcessExternalEntities(true); marshaller.unmarshal(new StreamSource("1")); assertNotNull(result.get()); assertEquals(false, result.get().getFeature("http://apache.org/xml/features/disallow-doctype-decl")); assertEquals(true, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); } @Test public void unmarshalSaxSourceWithXmlOptions() throws Exception { final AtomicReference<XMLReader> result = new AtomicReference<>(); CastorMarshaller marshaller = new CastorMarshaller() { @Override protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource) { result.set(xmlReader); return null; } }; // 1. external-general-entities and dtd support disabled (default) marshaller.unmarshal(new SAXSource(new InputSource("1"))); assertNotNull(result.get()); assertEquals(true, result.get().getFeature("http://apache.org/xml/features/disallow-doctype-decl")); assertEquals(false, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); // 2. external-general-entities and dtd support enabled result.set(null); marshaller.setSupportDtd(true); marshaller.setProcessExternalEntities(true); marshaller.unmarshal(new SAXSource(new InputSource("1"))); assertNotNull(result.get()); assertEquals(false, result.get().getFeature("http://apache.org/xml/features/disallow-doctype-decl")); assertEquals(true, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); } private Object unmarshalFlights() throws Exception { return unmarshal(INPUT_STRING); } private Object unmarshal(String xml) throws Exception { StreamSource source = new StreamSource(new StringReader(xml)); return unmarshaller.unmarshal(source); } }