All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.quarkus.resteasy.reactive.jaxb.runtime.serialisers.ServerJaxbMessageBodyWriter Maven / Gradle / Ivy

There is a newer version: 3.15.1
Show newest version
package io.quarkus.resteasy.reactive.jaxb.runtime.serialisers;

import java.beans.Introspector;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Map;

import javax.xml.namespace.QName;

import jakarta.inject.Inject;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.core.Context;
import jakarta.ws.rs.core.HttpHeaders;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.ext.Providers;
import jakarta.xml.bind.JAXBContext;
import jakarta.xml.bind.JAXBElement;
import jakarta.xml.bind.JAXBException;
import jakarta.xml.bind.Marshaller;
import jakarta.xml.bind.annotation.XmlRootElement;

import org.jboss.resteasy.reactive.server.spi.ServerMessageBodyWriter;
import org.jboss.resteasy.reactive.server.spi.ServerRequestContext;

import io.quarkus.jaxb.runtime.JaxbContextConfigRecorder;
import io.vertx.core.MultiMap;

public class ServerJaxbMessageBodyWriter extends ServerMessageBodyWriter.AllWriteableMessageBodyWriter {

    @Inject
    Marshaller marshaller;

    @Context
    Providers providers;

    @Override
    public void writeTo(Object o, Class type, Type genericType, Annotation[] annotations, MediaType mediaType,
            MultivaluedMap httpHeaders, OutputStream entityStream) throws WebApplicationException {
        setContentTypeIfNecessary(httpHeaders);
        marshal(o, entityStream);
    }

    @Override
    public void writeResponse(Object o, Type genericType, ServerRequestContext context)
            throws WebApplicationException, IOException {
        setContentTypeIfNecessary(context);
        OutputStream stream = context.getOrCreateOutputStream();
        marshal(o, stream);
        // we don't use try-with-resources because that results in writing to the http output without the exception mapping coming into play
        stream.close();
    }

    protected void marshal(Object o, OutputStream outputStream) {
        try {
            Class clazz = o.getClass();
            Object jaxbObject = o;
            if (o instanceof JAXBElement) {
                clazz = ((JAXBElement) o).getDeclaredType();
            } else {
                XmlRootElement jaxbElement = clazz.getAnnotation(XmlRootElement.class);
                if (jaxbElement == null) {
                    jaxbObject = new JAXBElement(new QName(Introspector.decapitalize(clazz.getSimpleName())), clazz, o);
                }
            }

            getMarshall(clazz).marshal(jaxbObject, outputStream);

        } catch (JAXBException e) {
            throw new RuntimeException(e);
        }
    }

    private Marshaller getMarshall(Class type) throws JAXBException {
        if (JaxbContextConfigRecorder.isClassBound(type)) {
            return marshaller;
        }

        return providers.getContextResolver(JAXBContext.class, MediaType.APPLICATION_XML_TYPE)
                .getContext(type)
                .createMarshaller();
    }

    private void setContentTypeIfNecessary(MultivaluedMap httpHeaders) {
        Object contentType = httpHeaders.getFirst(HttpHeaders.CONTENT_TYPE);
        if (isNotXml(contentType)) {
            httpHeaders.putSingle(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML);
        }
    }

    private void setContentTypeIfNecessary(ServerRequestContext context) {
        String currentContentType = null;
        Iterable> responseHeaders = context.serverResponse().getAllResponseHeaders();
        if (responseHeaders instanceof MultiMap) {
            currentContentType = ((MultiMap) responseHeaders).get(HttpHeaders.CONTENT_TYPE);
        } else {
            for (Map.Entry entry : responseHeaders) {
                if (entry.getKey().equalsIgnoreCase(HttpHeaders.CONTENT_TYPE)) {
                    currentContentType = entry.getValue();
                    break;
                }
            }
        }
        if (isNotXml(currentContentType)) {
            context.serverResponse().setResponseHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_XML);
        }
    }

    private boolean isNotXml(Object contentType) {
        return contentType == null || !contentType.toString().contains("xml");
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy