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

com.github.rmannibucau.playx.servlet.servlet.internal.ResponseAdapter Maven / Gradle / Ivy

The newest version!
package com.github.rmannibucau.playx.servlet.servlet.internal;

import static java.util.Optional.ofNullable;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Locale;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;

import javax.servlet.ServletContext;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;

import org.apache.pekko.util.ByteString;
import play.http.HttpEntity;
import play.mvc.Result;

public class ResponseAdapter implements HttpServletResponse {

    private final String requestUri;

    private final Collection cookies = new ArrayList<>();

    private final Map headers = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);

    private final ServletContext context;

    private int status = HttpServletResponse.SC_OK;

    private boolean commited;

    private String encoding;

    private int bufferSize = 8192;

    private Locale locale;

    private OutputStreamAdapter outputStream;

    private PrintWriter writer;

    // todo: stream?
    private ByteArrayOutputStream output = new ByteArrayOutputStream();

    private final CompletableFuture completion = new CompletableFuture<>();

    public ResponseAdapter(final String requestUri, final ServletContext context) {
        this.requestUri = requestUri;
        this.context = context;
    }

    public CompletionStage toResult() {
        return completion;
    }

    public void fail(final Throwable error) {
        if (completion.isDone()) {
            return;
        }
        try {
            flushBuffer();
        } catch (final IOException e) {
            // no-op
        }
        completion.completeExceptionally(error);
    }

    public void onComplete() {
        if (completion.isDone()) {
            return;
        }
        try {
            flushBuffer();
        } catch (final IOException e) {
            // no-op
        }
        final String contentType = headers.remove("Content-Type");
        headers.remove("Content-Length");
        completion.complete(new Result(status, headers,
                new HttpEntity.Strict(ByteString.fromArray(output.toByteArray()), ofNullable(contentType))));
    }

    private String base() {
        final URI uri = URI.create(requestUri);
        return uri.getScheme() + "://" + uri.getAuthority();
    }

    private String toEncoded(final String url) {
        return url;
    }

    @Override
    public void addCookie(final Cookie cookie) {
        cookies.add(cookie);
    }

    @Override
    public boolean containsHeader(final String name) {
        return headers.containsKey(name);
    }

    @Override
    public String encodeURL(final String s) {
        return toEncoded(s);
    }

    @Override
    public String encodeRedirectURL(final String s) {
        return toEncoded(s);
    }

    @Override
    public String encodeUrl(final String s) {
        return toEncoded(s);
    }

    @Override
    public String encodeRedirectUrl(final String s) {
        return encodeRedirectURL(s);
    }

    @Override
    public void sendError(final int sc, final String msg) {
        sendError(sc);
    }

    @Override
    public void sendError(final int sc) {
        setStatus(sc);
    }

    @Override
    public void sendRedirect(final String location) throws IOException {
        if (commited) {
            throw new IllegalStateException("response already committed");
        }
        resetBuffer();

        try {
            setStatus(SC_FOUND);

            setHeader("Location", base() + toEncoded(location));
        } catch (final IllegalArgumentException e) {
            setStatus(SC_NOT_FOUND);
        }
    }

    @Override
    public void setDateHeader(final String name, final long date) {
        addDateHeader(name, date);
    }

    @Override
    public void addDateHeader(final String name, final long date) {
        setHeader(name, Long.toString(date));
    }

    @Override
    public void setHeader(final String name, final String value) {
        addHeader(name, value);
    }

    @Override
    public void addHeader(final String name, final String value) {
        headers.put(name, value);
    }

    @Override
    public void setIntHeader(final String name, final int value) {
        addIntHeader(name, value);
    }

    @Override
    public void addIntHeader(final String name, final int value) {
        headers.put(name, Integer.toString(value));
    }

    @Override
    public void setStatus(final int sc) {
        status = sc;
    }

    @Override
    public void setStatus(final int sc, final String sm) {
        setStatus(sc);
    }

    @Override
    public int getStatus() {
        return status;
    }

    @Override
    public String getHeader(final String name) {
        return headers.get(name);
    }

    @Override
    public Collection getHeaders(final String name) {
        return ofNullable(headers.get(name)).map(Collections::singleton).orElseGet(Collections::emptySet);
    }

    @Override
    public Collection getHeaderNames() {
        return headers.keySet();
    }

    @Override
    public String getCharacterEncoding() {
        return ofNullable(encoding).orElseGet(context::getResponseCharacterEncoding);
    }

    @Override
    public String getContentType() {
        return getHeader("Content-Type");
    }

    @Override
    public ServletOutputStream getOutputStream() {
        return outputStream == null ? outputStream = new OutputStreamAdapter(output) : outputStream;
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        return writer == null ? writer = new PrintWriter(getOutputStream()) : writer;
    }

    @Override
    public void setCharacterEncoding(final String charset) {
        encoding = charset;
    }

    @Override
    public void setContentLength(final int len) {
        setHeader("Content-Length", Integer.toString(len));
    }

    @Override
    public void setContentLengthLong(final long length) {
        setHeader("Content-Length", Long.toString(length));
    }

    @Override
    public void setContentType(final String type) {
        setHeader("Content-Type", type);
    }

    @Override
    public void setBufferSize(final int size) {
        if (outputStream == null && writer == null) {
            output = new ByteArrayOutputStream(size);
            bufferSize = size;
        }
    }

    @Override
    public int getBufferSize() {
        return output.size();
    }

    @Override
    public void flushBuffer() throws IOException {
        if (writer != null) {
            writer.flush();
        }
        output.flush();
    }

    @Override
    public void resetBuffer() {
        output.reset();
    }

    @Override
    public boolean isCommitted() {
        return commited;
    }

    @Override
    public void reset() {
        output.reset();
    }

    @Override
    public void setLocale(final Locale loc) {
        locale = loc;
    }

    @Override
    public Locale getLocale() {
        return locale;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy