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

org.jboss.resteasy.reactive.client.handlers.ClientResponseCompleteRestHandler Maven / Gradle / Ivy

There is a newer version: 3.17.5
Show newest version
package org.jboss.resteasy.reactive.client.handlers;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;

import jakarta.ws.rs.core.GenericType;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;

import org.jboss.resteasy.reactive.client.impl.ClientResponseBuilderImpl;
import org.jboss.resteasy.reactive.client.impl.ClientResponseContextImpl;
import org.jboss.resteasy.reactive.client.impl.RestClientRequestContext;
import org.jboss.resteasy.reactive.client.impl.multipart.FileDownloadImpl;
import org.jboss.resteasy.reactive.client.spi.ClientRestHandler;
import org.jboss.resteasy.reactive.client.spi.FieldFiller;
import org.jboss.resteasy.reactive.client.spi.MultipartResponseData;
import org.jboss.resteasy.reactive.common.jaxrs.ResponseImpl;

import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.FileUpload;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;

public class ClientResponseCompleteRestHandler implements ClientRestHandler {

    @Override
    public void handle(RestClientRequestContext context) throws Exception {
        context.getResult().complete(mapToResponse(context, true));
    }

    public static ResponseImpl mapToResponse(RestClientRequestContext context,
            boolean parseContent)
            throws IOException {
        Map, MultipartResponseData> multipartDataMap = context.getMultipartResponsesData();
        ClientResponseContextImpl responseContext = context.getOrCreateClientResponseContext();
        ClientResponseBuilderImpl builder = new ClientResponseBuilderImpl();
        builder.status(responseContext.getStatus(), responseContext.getReasonPhrase());
        builder.setAllHeaders(responseContext.getHeaders());
        builder.invocationState(context);
        InputStream entityStream = responseContext.getEntityStream();
        if (context.isResponseTypeSpecified()
                // when we are returning a RestResponse, we don't want to do any parsing
                && (Response.Status.Family.familyOf(context.getResponseStatus()) == Response.Status.Family.SUCCESSFUL)
                && parseContent) { // this case means that a specific response type was requested
            if (context.getResponseMultipartParts() != null) {
                GenericType responseType = context.getResponseType();
                if (!(responseType.getType() instanceof Class)) {
                    throw new IllegalArgumentException("Not supported return type for a multipart message, " +
                            "expected a non-generic class got : " + responseType.getType());
                }
                Class responseClass = (Class) responseType.getType();
                MultipartResponseData multipartData = multipartDataMap.get(responseClass);
                if (multipartData == null) {
                    throw new IllegalStateException("Failed to find multipart data for class " + responseClass + ". " +
                            "If it's meant to be used as multipart response type, consider annotating it with @MultipartForm");
                }
                Object result = multipartData.newInstance();
                builder.entity(result);
                List parts = context.getResponseMultipartParts();
                for (InterfaceHttpData httpData : parts) {
                    FieldFiller fieldFiller = null;
                    // find the correct filler
                    for (FieldFiller ff : multipartData.getFieldFillers()) {
                        if (ff.getPartName().equals(httpData.getName())) {
                            fieldFiller = ff;
                            break;
                        }
                    }
                    if (fieldFiller == null) {
                        continue;
                    }
                    if (httpData instanceof Attribute at) {
                        // TODO: get rid of ByteArrayInputStream
                        // TODO: maybe we could extract something closer to input stream from attribute
                        ByteArrayInputStream in = new ByteArrayInputStream(
                                at.getValue().getBytes(StandardCharsets.UTF_8));
                        Object fieldValue = context.readEntity(in,
                                fieldFiller.getFieldType(),
                                MediaType.valueOf(fieldFiller.getMediaType()),
                                context.getMethodDeclaredAnnotationsSafe(),
                                // FIXME: we have strings, it wants objects, perhaps there's
                                // an Object->String conversion too many
                                (MultivaluedMap) responseContext.getHeaders());
                        if (fieldValue != null) {
                            fieldFiller.set(result, fieldValue);
                        }
                    } else if (httpData instanceof FileUpload fu) {
                        fieldFiller.set(result, new FileDownloadImpl(fu));
                    } else {
                        throw new IllegalArgumentException("Unsupported multipart message element type. " +
                                "Expected FileAttribute or Attribute, got: " + httpData.getClass());
                    }
                }
            } else {
                Class rawType = context.getResponseType().getRawType();
                if (context.isFileDownload()) {
                    if (File.class.equals(rawType)) {
                        builder.entity(new File(context.getTmpFilePath()));
                    } else if (Path.class.equals(rawType)) {
                        builder.entity(Paths.get(context.getTmpFilePath()));
                    } else {
                        throw new IllegalStateException("Unhandled type: " + rawType);
                    }
                    context.clearTmpFilePath();
                } else if (!void.class.equals(rawType)) {
                    Object entity = context.readEntity(entityStream,
                            context.getResponseType(),
                            responseContext.getMediaType(),
                            context.getMethodDeclaredAnnotationsSafe(),
                            // FIXME: we have strings, it wants objects, perhaps there's
                            // an Object->String conversion too many
                            (MultivaluedMap) responseContext.getHeaders());
                    if (entity != null) {
                        builder.entity(entity);
                    }
                }
            }
        } else {
            // in this case no specific response type was requested so we just prepare the stream
            // the users of the response are meant to use readEntity
            builder.entityStream(entityStream);
        }
        return builder.build();
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy