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

io.helidon.security.jersey.SingleSubscriberHolder Maven / Gradle / Ivy

There is a newer version: 0.10.6
Show newest version
/*
 * Copyright (c) 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.helidon.security.jersey;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.Consumer;

import io.helidon.common.reactive.Flow;

/**
 * A subscriber container that accepts only a single, one-time subscriber registration.
 */
@SuppressWarnings("WeakerAccess")
class SingleSubscriberHolder {
    private final CompletableFuture> subscriber = new CompletableFuture<>();
    private final AtomicBoolean closed = new AtomicBoolean(false);

    /**
     * Register a new subscriber.
     * 

* In case the subscriber registration fails (e.g. the holder already holds a previously registered subscriber * or the holder has been {@link #close(Consumer) closed}), the newly registered subscriber is notified about the * error by invoking it's {@link Flow.Subscriber#onError(Throwable) subscriber.onError} method. * * @param subscriber subscriber to be registered in the holder. * @return {@code true} if the subscriber was successfully registered, {@code false} otherwise. */ public boolean register(Flow.Subscriber subscriber) { if (!this.subscriber.complete(subscriber)) { Throwable error = null; try { this.subscriber.get(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); error = e; } catch (ExecutionException e) { error = e.getCause(); } subscriber.onError((error != null) ? error : new IllegalStateException( "This publisher only supports a single subscriber.")); return false; } return true; } /** * Mark the subscriber holder as closed. *

* Invoking this method will ensure that any new attempts to {@link #register(Flow.Subscriber) register} a new subscriber * would fail. *

* In case this holder holds a subscriber and the close method has not been invoked yet, the supplied * {@code completionHandler} is invoked using the value of the registered subscriber as an input parameter. * This means that the supplied completion handler is guaranteed to be invoked at most once. * * @param completionHandler completion handler to be invoked to process any completion logic on a registered subscriber, * provided there is a registered subscriber and it has not been previously passed to a completion * handler (e.g. in a previous invocation of this method). */ public void close(Consumer> completionHandler) { if (!subscriber.completeExceptionally(new IllegalStateException("Publisher already closed.")) && closed.compareAndSet(false, true)) { try { final Flow.Subscriber s = this.subscriber.get(); completionHandler.accept(s); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } catch (ExecutionException e) { // ignore } } } /** * Get the stored subscriber. *

* This method blocks indefinitely until a subscriber is registered or the holder has been closed. * * @return registered subscriber. * @throws ExecutionException if the subscriber retrieval has failed (e.g. because this holder has been closed * before a subscriber has been registered). * @throws InterruptedException if the current thread was interrupted */ public Flow.Subscriber get() throws InterruptedException, ExecutionException { return subscriber.get(); } /** * Check if this subscriber holder has been closed. * * @return {@code true} if the holder is closed, {@code false} otherwise. */ public boolean isClosed() { return closed.get(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy