package com.github.aesteve.vertx.nubes.marshallers.impl; import com.github.aesteve.vertx.nubes.exceptions.MarshallingException; import com.github.aesteve.vertx.nubes.marshallers.PayloadMarshaller; import com.github.aesteve.vertx.nubes.utils.StackTracePrinter; import io.vertx.core.VertxException; import org.w3c.dom.Document; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import java.io.IOException; import java.io.StringReader; import java.io.StringWriter; import java.util.Set; import static com.github.aesteve.vertx.nubes.marshallers.PayloadMarshaller.Constants.ERROR_CODE_KEY; import static com.github.aesteve.vertx.nubes.marshallers.PayloadMarshaller.Constants.ERROR_KEY; import static com.github.aesteve.vertx.nubes.marshallers.PayloadMarshaller.Constants.ERROR_MESSAGE_KEY; public class JAXBPayloadMarshaller implements PayloadMarshaller { protected Marshaller marshaller; protected Unmarshaller unmarshaller; public JAXBPayloadMarshaller(Set<Class<?>> classes) throws JAXBException { JAXBContext jc = JAXBContext.newInstance(classes.toArray(new Class<?>[0])); marshaller = jc.createMarshaller(); unmarshaller = jc.createUnmarshaller(); } @Override public <T> T unmarshallPayload(String body, Class<T> clazz) { try { return unmarshaller.unmarshal(loadXMLFromString(body), clazz).getValue(); } catch (MarshallingException | JAXBException e) { throw new VertxException(e); } } @Override public String marshallPayload(Object payload) { StringWriter writer = new StringWriter(); try { marshaller.marshal(payload, writer); } catch (JAXBException je) { throw new VertxException(je); } return writer.toString(); } public static Document loadXMLFromString(String xml) throws MarshallingException { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder; try { builder = factory.newDocumentBuilder(); } catch (ParserConfigurationException e) { throw new MarshallingException(e); } try (StringReader reader = new StringReader(xml)){ return builder.parse(new InputSource(reader)); } catch (SAXException | IOException e) { throw new MarshallingException(e); } } @Override public String marshallUnexpectedError(Throwable error, boolean displayDetails) { return marshallError(500, error, null); } @Override public String marshallHttpStatus(int statusCode, String errorMessage) { return marshallError(statusCode, null, errorMessage); } private static String marshallError(int status, Throwable error, String message) { String errorMsg = message; if (message == null && error != null) { errorMsg = StackTracePrinter.asLineString(new StringBuilder(), error).toString(); } return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" + "<" + ERROR_KEY + ">\n" + "\t<" + ERROR_CODE_KEY + ">" + status + "</" + ERROR_CODE_KEY + ">\n" + "\t<" + ERROR_MESSAGE_KEY + ">\n<![CDATA[" + errorMsg + "]]>\n\t</" + ERROR_MESSAGE_KEY + ">\n" + "</" + ERROR_KEY + ">"; } }