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

io.micronaut.http.netty.AbstractCompositeCustomizer Maven / Gradle / Ivy

There is a newer version: 4.7.5
Show newest version
/*
 * Copyright 2017-2022 original authors
 *
 * 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
 *
 * https://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.micronaut.http.netty;

import io.micronaut.core.annotation.Internal;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.order.OrderUtil;
import io.netty.channel.Channel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.function.Consumer;

/**
 * Base class for the composite customizers for the client and server. The APIs are structured
 * quite similarly, but it doesn't make sense to merge them because writing generic code for them
 * does not make sense, so this class exists to at least merge the composition behavior (ordering
 * and such).
 *
 * @param  The actual customizer class. Must also be implemented by the
 * {@link AbstractCompositeCustomizer} subclass.
 * @param  The ChannelRole type.
 */
@Internal
public abstract class AbstractCompositeCustomizer {
    private static final Logger LOG = LoggerFactory.getLogger(AbstractCompositeCustomizer.class);

    private final List members;

    protected AbstractCompositeCustomizer(List members) {
        this.members = members;
    }

    protected AbstractCompositeCustomizer() {
        this(new CopyOnWriteArrayList<>());
    }

    /**
     * Add customizer.
     *
     * @param customizer Customizer
     */
    public synchronized void add(C customizer) {
        assert members instanceof CopyOnWriteArrayList : "only allow adding to root customizer";
        // do the insertion in one operation, so that concurrent readers don't see an inconsistent
        // (unsorted) state
        int insertionIndex = Collections.binarySearch(members, customizer, OrderUtil.COMPARATOR);
        if (insertionIndex < 0) {
            insertionIndex = ~insertionIndex;
        }
        members.add(insertionIndex, customizer);
    }

    protected abstract C specializeForChannel(C member, Channel channel, R role);

    protected abstract C makeNewComposite(List members);

    @NonNull
    public final C specializeForChannel(@NonNull Channel channel, @NonNull R role) {
        List specialized = null;
        for (int i = 0; i < this.members.size(); i++) {
            C old = this.members.get(i);
            C nev;
            try {
                nev = specializeForChannel(old, channel, role);
                Objects.requireNonNull(nev, "specializeForChannel must not return null");
            } catch (Exception e) {
                LOG.error("Failed to specialize customizer", e);
                nev = old;
            }
            if (specialized == null) {
                if (nev == old) {
                    continue;
                }
                specialized = new ArrayList<>(this.members.size());
                specialized.addAll(this.members.subList(0, i));
            }
            specialized.add(nev);
        }
        if (specialized == null) {
            //noinspection unchecked
            return (C) this;
        } else {
            return makeNewComposite(specialized);
        }
    }

    protected final void forEach(Consumer consumer) {
        for (C member : members) {
            try {
                consumer.accept(member);
            } catch (Exception e) {
                LOG.error("Failed to trigger customizer event", e);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy