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

org.wildfly.httpclient.common.WildflyHttpContext Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2022 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * 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 org.wildfly.httpclient.common;

import io.undertow.UndertowOptions;
import io.undertow.connector.ByteBufferPool;
import io.undertow.server.DefaultByteBufferPool;
import org.wildfly.common.context.ContextManager;
import org.wildfly.common.context.Contextual;
import org.xnio.OptionMap;
import org.xnio.XnioWorker;

import java.net.InetSocketAddress;
import java.net.URI;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static java.security.AccessController.doPrivileged;

/**
 * Represents the current configured state of the HTTP contexts.
 *
 * @author Stuart Douglas
 * @author Flavia Rainone
 */
public class WildflyHttpContext implements Contextual {

    private static final int LEAK_DETECTION = Integer.getInteger("org.wildfly.http-client.buffer-leak-detection", 0);

    /**
     * The context manager for HTTP endpoints.
     */
    static ContextManager HTTP_CONTEXT_MANAGER = doPrivileged((PrivilegedAction>) () -> {
        final ContextManager contextManager = new ContextManager<>(WildflyHttpContext.class, "jboss-ejb-http-client.http-context");
        contextManager.setGlobalDefaultSupplierIfNotSet(ConfigurationHttpContextSupplier::new);
        return contextManager;
    });

    /**
     * TODO: figure out some way to remove these when all the connections are closed, it has the potential to be very racey
     */
    private final Map uriConnectionPools = new ConcurrentHashMap<>();

    private final ConfigSection[] targets;

    private final int maxConnections;
    private final int maxStreamsPerConnection;
    private final long idleTimeout;
    private final boolean eagerlyAcquireAffinity;
    private final XnioWorker worker;
    private final ByteBufferPool pool;
    private final boolean enableHttp2;
    private final HttpConnectionPoolFactory httpConnectionPoolFactory;
    private final HttpMarshallerFactoryProvider httpMarshallerFactoryProvider;

    WildflyHttpContext(ConfigSection[] targets, int maxConnections, int maxStreamsPerConnection, long idleTimeout, boolean eagerlyAcquireAffinity, XnioWorker worker, ByteBufferPool pool, boolean enableHttp2,
                       HttpConnectionPoolFactory httpConnectionPoolFactory, HttpMarshallerFactoryProvider httpMarshallerFactoryProvider) {
        this.targets = targets;
        this.maxConnections = maxConnections;
        this.maxStreamsPerConnection = maxStreamsPerConnection;
        this.idleTimeout = idleTimeout;
        this.eagerlyAcquireAffinity = eagerlyAcquireAffinity;
        this.worker = worker;
        this.pool = pool;
        this.enableHttp2 = enableHttp2;
        this.httpConnectionPoolFactory = httpConnectionPoolFactory;
        this.httpMarshallerFactoryProvider = httpMarshallerFactoryProvider;
    }

    public static WildflyHttpContext getCurrent() {
        return HttpContextGetterHolder.SUPPLIER.get();
    }

    @Override
    public ContextManager getInstanceContextManager() {
        return HTTP_CONTEXT_MANAGER;
    }

    public HttpTargetContext getTargetContext(final URI uri) {
        return getConnectionPoolForURI(uri);
    }

    private HttpTargetContext getConnectionPoolForURI(URI uri) {
        HttpTargetContext context = uriConnectionPools.get(uri);
        if (context != null) {
            context.init();
            return context;
        }
        for (ConfigSection target : targets) {
            if (target.getUri().equals(uri)) {
                target.getHttpTargetContext().init();
                uriConnectionPools.put(uri, target.getHttpTargetContext());
                return target.getHttpTargetContext();
            }
        }
        synchronized (this) {
            context = uriConnectionPools.get(uri);
            if (context != null) {
                return context;
            }
            HttpConnectionPool pool = httpConnectionPoolFactory.createHttpConnectionPool(
                    maxConnections, maxStreamsPerConnection, worker, this.pool, OptionMap.create(UndertowOptions.ENABLE_HTTP2, enableHttp2), new HostPool(uri), idleTimeout);
            uriConnectionPools.put(uri, context = new HttpTargetContext(pool, eagerlyAcquireAffinity, uri, httpMarshallerFactoryProvider));
            context.init();
            return context;
        }
    }

    static class ConfigSection {
        private final HttpTargetContext httpTargetContext;
        private final URI uri;

        ConfigSection(HttpTargetContext httpTargetContext, URI uri) {
            this.httpTargetContext = httpTargetContext;
            this.uri = uri;
        }

        public HttpTargetContext getHttpTargetContext() {
            return httpTargetContext;
        }

        public URI getUri() {
            return uri;
        }
    }

    static class Builder {
        private InetSocketAddress defaultBindAddress;
        private long idleTimeout = 50000; //the server defaults to an idle timeout of 60 seconds, we default ours to 50 to prevent possible races
        private int maxConnections;
        private int maxStreamsPerConnection;
        private Boolean eagerlyAcquireSession;
        private final List targets = new ArrayList<>();
        private Boolean enableHttp2;

        private BufferBuilder bufferConfig;

        WildflyHttpContext build() {

            XnioWorker worker = XnioWorker.getContextManager().get();
            ByteBufferPool pool;
            if(bufferConfig == null) {
            pool=new DefaultByteBufferPool(true, 1024, 100, 0, LEAK_DETECTION); //TODO
            } else {
                pool = new DefaultByteBufferPool(bufferConfig.isDirect(), bufferConfig.getBufferSize(), bufferConfig.getMaxSize(), bufferConfig.getThreadLocalSize(), LEAK_DETECTION);
            }
            //TODO: ssl config
            ConfigSection[] connections = new ConfigSection[this.targets.size()];

            long idleTimout = this.idleTimeout > 0 ? this.idleTimeout : 60000;
            int maxConnections = this.maxConnections > 0 ? this.maxConnections : 10;
            int maxStreamsPerConnection = this.maxStreamsPerConnection > 0 ? this.maxStreamsPerConnection : 10;

            final HttpConnectionPoolFactory httpConnectionPoolFactory;
            final HttpMarshallerFactoryProvider httpMarshallerFactoryProvider;
            if (EENamespaceInteroperability.EE_NAMESPACE_INTEROPERABLE_MODE) {
                httpConnectionPoolFactory = EENamespaceInteroperability.getHttpConnectionPoolFactory();
                httpMarshallerFactoryProvider = EENamespaceInteroperability.getHttpMarshallerFactoryProvider();
            } else {
                httpConnectionPoolFactory = HttpConnectionPoolFactory.getDefault();
                httpMarshallerFactoryProvider = HttpMarshallerFactoryProvider.getDefaultHttpMarshallerFactoryProvider();
            }
            for (int i = 0; i < this.targets.size(); ++i) {
                HttpConfigBuilder sb = this.targets.get(i);
                HostPool hp = new HostPool(sb.getUri());
                boolean eager = this.eagerlyAcquireSession == null ? false : this.eagerlyAcquireSession;
                if (sb.getEagerlyAcquireSession() != null && sb.getEagerlyAcquireSession()) {
                    eager = true;
                }
                boolean http2 = this.enableHttp2 == null ? true : this.enableHttp2;
                if(sb.getEnableHttp2() != null) {
                    http2 = sb.getEnableHttp2();
                }
                ConfigSection connection = new ConfigSection(new HttpTargetContext(
                        httpConnectionPoolFactory.createHttpConnectionPool(sb.getMaxConnections() > 0 ? sb.getMaxConnections() : maxConnections, sb.getMaxStreamsPerConnection() > 0 ? sb.getMaxStreamsPerConnection() : maxStreamsPerConnection, worker, pool, OptionMap.create(UndertowOptions.ENABLE_HTTP2, http2),
                                hp, sb.getIdleTimeout() > 0 ? sb.getIdleTimeout() : idleTimout), eager, sb.getUri(), httpMarshallerFactoryProvider),
                        sb.getUri());
                connections[i] = connection;
            }
            return new WildflyHttpContext(connections, maxConnections, maxStreamsPerConnection, idleTimeout,
                    eagerlyAcquireSession == null ? false : eagerlyAcquireSession, worker, pool, enableHttp2 == null ? true : enableHttp2,
                    httpConnectionPoolFactory, httpMarshallerFactoryProvider);
        }

        void setDefaultBindAddress(InetSocketAddress defaultBindAddress) {
            this.defaultBindAddress = defaultBindAddress;
        }

        InetSocketAddress getDefaultBindAddress() {
            return defaultBindAddress;
        }

        HttpConfigBuilder addConfig(URI uri) {
            HttpConfigBuilder builder = new HttpConfigBuilder(uri);
            targets.add(builder);
            return builder;
        }

        List getTargets() {
            return targets;
        }


        long getIdleTimeout() {
            return idleTimeout;
        }

        void setIdleTimeout(long idleTimeout) {
            this.idleTimeout = idleTimeout;
        }

        int getMaxConnections() {
            return maxConnections;
        }

        void setMaxConnections(int maxConnections) {
            this.maxConnections = maxConnections;
        }

        int getMaxStreamsPerConnection() {
            return maxStreamsPerConnection;
        }

        void setMaxStreamsPerConnection(int maxStreamsPerConnection) {
            this.maxStreamsPerConnection = maxStreamsPerConnection;
        }

        Boolean getEagerlyAcquireSession() {
            return eagerlyAcquireSession;
        }

        void setEagerlyAcquireSession(Boolean eagerlyAcquireSession) {
            this.eagerlyAcquireSession = eagerlyAcquireSession;
        }

        public BufferBuilder getBufferConfig() {
            return bufferConfig;
        }

        public Builder setBufferConfig(BufferBuilder bufferConfig) {
            this.bufferConfig = bufferConfig;
            return this;
        }

        public void setEnableHttp2(Boolean enableHttp2) {
            this.enableHttp2 = enableHttp2;
        }

        public Boolean getEnableHttp2() {
            return enableHttp2;
        }

        class HttpConfigBuilder {
            final URI uri;
            private InetSocketAddress bindAddress;
            private long idleTimeout;
            private int maxConnections;
            private int maxStreamsPerConnection;
            private Boolean eagerlyAcquireSession;
            private Boolean enableHttp2;

            HttpConfigBuilder(URI uri) {
                this.uri = uri;
            }

            public URI getUri() {
                return uri;
            }

            void setBindAddress(InetSocketAddress bindAddress) {
                this.bindAddress = bindAddress;
            }

            InetSocketAddress getBindAddress() {
                return bindAddress;
            }

            long getIdleTimeout() {
                return idleTimeout;
            }

            void setIdleTimeout(long idleTimeout) {
                this.idleTimeout = idleTimeout;
            }

            int getMaxConnections() {
                return maxConnections;
            }

            void setMaxConnections(int maxConnections) {
                this.maxConnections = maxConnections;
            }

            int getMaxStreamsPerConnection() {
                return maxStreamsPerConnection;
            }

            void setMaxStreamsPerConnection(int maxStreamsPerConnection) {
                this.maxStreamsPerConnection = maxStreamsPerConnection;
            }

            Boolean getEagerlyAcquireSession() {
                return eagerlyAcquireSession;
            }

            void setEagerlyAcquireSession(Boolean eagerlyAcquireSession) {
                this.eagerlyAcquireSession = eagerlyAcquireSession;
            }

            public void setEnableHttp2(Boolean enableHttp2) {
                this.enableHttp2 = enableHttp2;
            }

            public Boolean getEnableHttp2() {
                return enableHttp2;
            }
        }
    }

    public static class BufferBuilder {
        private int bufferSize = 1024;
        private int maxSize = 100;
        private int threadLocalSize = 0;
        private boolean direct = true;

        public int getBufferSize() {
            return bufferSize;
        }

        public BufferBuilder setBufferSize(int bufferSize) {
            this.bufferSize = bufferSize;
            return this;
        }

        public int getMaxSize() {
            return maxSize;
        }

        public BufferBuilder setMaxSize(int maxSize) {
            this.maxSize = maxSize;
            return this;
        }

        public int getThreadLocalSize() {
            return threadLocalSize;
        }

        public BufferBuilder setThreadLocalSize(int threadLocalSize) {
            this.threadLocalSize = threadLocalSize;
            return this;
        }

        public boolean isDirect() {
            return direct;
        }

        public BufferBuilder setDirect(boolean direct) {
            this.direct = direct;
            return this;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy