package rocks.inspectit.shared.cs.jaxb; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; import static org.hamcrest.Matchers.nullValue; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.Charset; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.List; import javax.xml.bind.JAXBContext; import javax.xml.bind.UnmarshalException; import javax.xml.bind.Unmarshaller; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import org.mockito.InjectMocks; import org.testng.annotations.AfterTest; import org.testng.annotations.Test; import org.w3c.dom.Document; import org.w3c.dom.Element; import rocks.inspectit.shared.all.testbase.TestBase; /** * @author Ivan Senic * */ public class JAXBTransformatorTest extends TestBase { @InjectMocks JAXBTransformator transformator; Path path = Paths.get("tst.xml").toAbsolutePath(); @AfterTest public void clean() throws IOException { Files.deleteIfExists(path); } public static class Marshall extends JAXBTransformatorTest { @Test public void basic() throws Exception { String value = "value"; TestData testData = new TestData(); testData.setValue(value); transformator.marshall(path, testData, null); assertThat(Files.exists(path), is(true)); JAXBContext context = JAXBContext.newInstance(TestData.class); Unmarshaller unmarshaller = context.createUnmarshaller(); try (InputStream is = Files.newInputStream(path, StandardOpenOption.READ)) { Object unmarshaled = unmarshaller.unmarshal(is); assertThat(unmarshaled, is((Object) testData)); } } @Test public void schemaVersion() throws Exception { String value = "value"; int schemaVersion = 11; TestData testData = new TestData(); testData.setValue(value); transformator.marshall(path, testData, null, schemaVersion); assertThat(testData.getSchemaVersion(), is(schemaVersion)); JAXBContext context = JAXBContext.newInstance(TestData.class); Unmarshaller unmarshaller = context.createUnmarshaller(); try (InputStream is = Files.newInputStream(path, StandardOpenOption.READ)) { Object unmarshaled = unmarshaller.unmarshal(is); assertThat(unmarshaled, is((Object) testData)); } } @Test public void schemaLocation() throws Exception { String schemaLocation = "something.xsd"; transformator.marshall(path, new TestData(), schemaLocation); try (InputStream is = Files.newInputStream(path, StandardOpenOption.READ)) { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document document = dBuilder.parse(is); Element element = document.getDocumentElement(); element.normalize(); assertThat(element.hasAttribute("xsi:noNamespaceSchemaLocation"), is(true)); assertThat(element.getAttribute("xsi:noNamespaceSchemaLocation"), is(schemaLocation)); } } @Test(expectedExceptions = IOException.class) public void directoryAsPath() throws Exception { transformator.marshall(path.getParent(), new TestData(), null); } @Test public void bytesBasic() throws Exception { String value = "value"; TestData testData = new TestData(); testData.setValue(value); byte[] data = transformator.marshall(testData, null); assertThat(Files.exists(path), is(true)); JAXBContext context = JAXBContext.newInstance(TestData.class); Unmarshaller unmarshaller = context.createUnmarshaller(); try (InputStream is = new ByteArrayInputStream(data)) { Object unmarshaled = unmarshaller.unmarshal(is); assertThat(unmarshaled, is((Object) testData)); } } @Test public void bytesSchemaVersion() throws Exception { String value = "value"; int schemaVersion = 11; TestData testData = new TestData(); testData.setValue(value); byte[] data = transformator.marshall(testData, null, schemaVersion); assertThat(testData.getSchemaVersion(), is(schemaVersion)); JAXBContext context = JAXBContext.newInstance(TestData.class); Unmarshaller unmarshaller = context.createUnmarshaller(); try (InputStream is = new ByteArrayInputStream(data)) { Object unmarshaled = unmarshaller.unmarshal(is); assertThat(unmarshaled, is((Object) testData)); } } @Test public void bytesSchemaLocation() throws Exception { String schemaLocation = "something.xsd"; byte[] data = transformator.marshall(new TestData(), schemaLocation); try (InputStream is = new ByteArrayInputStream(data)) { DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance(); DocumentBuilder dBuilder = dbFactory.newDocumentBuilder(); Document document = dBuilder.parse(is); Element element = document.getDocumentElement(); element.normalize(); assertThat(element.hasAttribute("xsi:noNamespaceSchemaLocation"), is(true)); assertThat(element.getAttribute("xsi:noNamespaceSchemaLocation"), is(schemaLocation)); } } @Test public void overwriteExistingFile() throws Exception { String initialValue = "initialValue"; TestData testData1 = new TestData(); testData1.setValue(initialValue); transformator.marshall(path, testData1, null); JAXBContext context = JAXBContext.newInstance(TestData.class); Unmarshaller unmarshaller = context.createUnmarshaller(); try (InputStream is = Files.newInputStream(path, StandardOpenOption.READ)) { Object unmarshaled = unmarshaller.unmarshal(is); assertThat(unmarshaled, is((Object) testData1)); } String overwrittenValue = "overwrittenValue"; TestData testData2 = new TestData(); testData2.setValue(overwrittenValue); transformator.marshall(path, testData2, null); try (InputStream is = Files.newInputStream(path, StandardOpenOption.READ)) { Object unmarshaled = unmarshaller.unmarshal(is); assertThat(unmarshaled, is((Object) testData2)); } } } public static class Unmarshal extends JAXBTransformatorTest { private Path schemaPath = Paths.get("src", "test", "resources", "rocks", "inspectit", "shared", "cs", "jaxb", "schema.xsd").toAbsolutePath(); private Path invalidSchemaPath = Paths.get("src", "test", "resources", "rocks", "inspectit", "shared", "cs", "jaxb", "schemaInvalid.xsd").toAbsolutePath(); private Path migrationPath = schemaPath.getParent().resolve("migration"); @Test public void basic() throws Exception { String value = "value"; TestData testData = new TestData(); testData.setValue(value); transformator.marshall(path, testData, null); TestData unmarshalled = transformator.unmarshall(path, schemaPath, TestData.class); assertThat(unmarshalled, is(testData)); } @Test(expectedExceptions = UnmarshalException.class) public void schemaNotValid() throws Exception { String value = "value"; TestData testData = new TestData(); testData.setValue(value); transformator.marshall(path, testData, null); transformator.unmarshall(path, invalidSchemaPath, TestData.class); } @Test public void schemaVersionUpToDate() throws Exception { int schemaVersion = 10; String value = "value"; TestData testData = new TestData(); testData.setValue(value); transformator.marshall(path, testData, null, schemaVersion); TestData unmarshalled = transformator.unmarshall(path, schemaPath, schemaVersion, migrationPath, TestData.class); assertThat(unmarshalled, is(testData)); } @Test public void schemaVersionNotUpToDate() throws Exception { int schemaVersion = 0; String value = "value"; TestData testData = new TestData(); testData.setValue(value); transformator.marshall(path, testData, null, schemaVersion); // manually remove the value attribute List<String> update = new ArrayList<>(); List<String> lines = Files.readAllLines(path, Charset.defaultCharset()); for (String line : lines) { if (line.contains("value=")) { line = line.replace("value=\"value\"", ""); } update.add(line); } Files.write(path, update, Charset.defaultCharset()); TestData unmarshalled = transformator.unmarshall(path, schemaPath, schemaVersion + 1, migrationPath, TestData.class); assertThat(unmarshalled.getSchemaVersion(), is(1)); assertThat(unmarshalled.getValue(), is("bar")); } @Test public void directoryAsPath() throws Exception { TestData unmarshalled = transformator.unmarshall(path.getParent(), schemaPath, TestData.class); assertThat(unmarshalled, is(nullValue())); } @Test public void notExistingPath() throws Exception { TestData unmarshalled = transformator.unmarshall(Paths.get("something.xml").toAbsolutePath(), schemaPath, TestData.class); assertThat(unmarshalled, is(nullValue())); } @Test public void bytesBasic() throws Exception { String value = "value"; TestData testData = new TestData(); testData.setValue(value); byte[] data = transformator.marshall(testData, null); TestData unmarshalled = transformator.unmarshall(data, schemaPath, TestData.class); assertThat(unmarshalled, is(testData)); } @Test(expectedExceptions = UnmarshalException.class) public void bytesSchemaNotValid() throws Exception { String value = "value"; TestData testData = new TestData(); testData.setValue(value); byte[] data = transformator.marshall(testData, null); transformator.unmarshall(data, invalidSchemaPath, TestData.class); } @Test public void bytesSchemaVersionUpToDate() throws Exception { int schemaVersion = 10; String value = "value"; TestData testData = new TestData(); testData.setValue(value); byte[] data = transformator.marshall(testData, null, schemaVersion); TestData unmarshalled = transformator.unmarshall(data, schemaPath, schemaVersion, migrationPath, TestData.class); assertThat(unmarshalled, is(testData)); } @Test public void bytesSchemaVersionNotUpToDate() throws Exception { int schemaVersion = 0; String value = "value"; TestData testData = new TestData(); testData.setValue(value); byte[] data = transformator.marshall(testData, null, schemaVersion); String dataAsString = new String(data); // manually remove the value attribute dataAsString = dataAsString.replace("value=\"value\"", ""); data = dataAsString.getBytes(); TestData unmarshalled = transformator.unmarshall(data, schemaPath, schemaVersion + 1, migrationPath, TestData.class); assertThat(unmarshalled.getSchemaVersion(), is(1)); assertThat(unmarshalled.getValue(), is("bar")); } } }