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

org.jboss.resteasy.reactive.server.jaxrs.SseEventSinkImpl Maven / Gradle / Ivy

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

import java.util.Collections;
import java.util.concurrent.CompletionStage;
import java.util.function.Consumer;

import jakarta.ws.rs.sse.OutboundSseEvent;
import jakarta.ws.rs.sse.SseEventSink;

import org.jboss.resteasy.reactive.server.core.ResteasyReactiveRequestContext;
import org.jboss.resteasy.reactive.server.core.SseUtil;
import org.jboss.resteasy.reactive.server.spi.ServerHttpResponse;

public class SseEventSinkImpl implements SseEventSink {

    public static final byte[] EMPTY_BUFFER = new byte[0];
    private ResteasyReactiveRequestContext context;
    private SseBroadcasterImpl broadcaster;
    private boolean closed;

    public SseEventSinkImpl(ResteasyReactiveRequestContext context) {
        this.context = context;
    }

    @Override
    public synchronized boolean isClosed() {
        return context.serverResponse().closed() || closed;
    }

    @Override
    public CompletionStage send(OutboundSseEvent event) {
        if (isClosed())
            throw new IllegalStateException("Already closed");
        // NOTE: we can't cast event to OutboundSseEventImpl because the TCK sends us its own subclass
        return SseUtil.send(context, event, Collections.emptyList());
    }

    @Override
    public synchronized void close() {
        if (closed)
            return;
        closed = true;
        ServerHttpResponse response = context.serverResponse();
        if (!response.closed()) {
            if (!response.headWritten()) {
                // make sure we send the headers if we're closing this sink before the
                // endpoint method is over
                SseUtil.setHeaders(context, response);
            }
            response.end();
            context.close();
        }
        if (broadcaster != null)
            broadcaster.fireClose(this);
    }

    public void sendInitialResponse(ServerHttpResponse response) {
        if (!response.headWritten()) {
            SseUtil.setHeaders(context, response);
            // send the headers over the wire
            context.suspend();
            response.write(EMPTY_BUFFER, new Consumer() {
                @Override
                public void accept(Throwable throwable) {
                    if (throwable == null) {
                        context.resume();
                    } else {
                        context.resume(throwable);
                    }
                    // I don't think we should be firing the exception on the broadcaster here
                }
            });
        }
        response.addCloseHandler(this::close);
    }

    void register(SseBroadcasterImpl broadcaster) {
        if (this.broadcaster != null)
            throw new IllegalStateException("Already registered on a broadcaster");
        this.broadcaster = broadcaster;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy