View Javadoc
1   /*
2    * ====================================================================
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   * ====================================================================
20   *
21   * This software consists of voluntary contributions made by many
22   * individuals on behalf of the Apache Software Foundation.  For more
23   * information on the Apache Software Foundation, please see
24   * <http://www.apache.org/>.
25   *
26   */
27  package org.apache.hc.core5.http2.impl.nio.bootstrap;
28  
29  import java.util.ArrayList;
30  import java.util.List;
31  
32  import org.apache.hc.core5.function.Callback;
33  import org.apache.hc.core5.function.Decorator;
34  import org.apache.hc.core5.function.Supplier;
35  import org.apache.hc.core5.http.config.CharCodingConfig;
36  import org.apache.hc.core5.http.impl.DefaultAddressResolver;
37  import org.apache.hc.core5.http.nio.AsyncPushConsumer;
38  import org.apache.hc.core5.http.nio.ssl.TlsStrategy;
39  import org.apache.hc.core5.http.protocol.HttpProcessor;
40  import org.apache.hc.core5.http.protocol.RequestHandlerRegistry;
41  import org.apache.hc.core5.http.protocol.UriPatternType;
42  import org.apache.hc.core5.http2.config.H2Config;
43  import org.apache.hc.core5.http2.impl.H2Processors;
44  import org.apache.hc.core5.http2.impl.nio.ClientH2StreamMultiplexerFactory;
45  import org.apache.hc.core5.http2.impl.nio.ClientH2PrefaceHandler;
46  import org.apache.hc.core5.http2.impl.nio.H2StreamListener;
47  import org.apache.hc.core5.http2.nio.support.DefaultAsyncPushConsumerFactory;
48  import org.apache.hc.core5.http2.ssl.H2ClientTlsStrategy;
49  import org.apache.hc.core5.reactor.IOReactorConfig;
50  import org.apache.hc.core5.reactor.IOSession;
51  import org.apache.hc.core5.reactor.IOSessionListener;
52  import org.apache.hc.core5.util.Args;
53  
54  /**
55   * {@link H2MultiplexingRequester} bootstrap.
56   *
57   * @since 5.0
58   */
59  public class H2MultiplexingRequesterBootstrap {
60  
61      private final List<HandlerEntry<Supplier<AsyncPushConsumer>>> pushConsumerList;
62      private UriPatternType uriPatternType;
63      private IOReactorConfig ioReactorConfig;
64      private HttpProcessor httpProcessor;
65      private CharCodingConfig charCodingConfig;
66      private H2Config h2Config;
67      private TlsStrategy tlsStrategy;
68      private boolean strictALPNHandshake;
69      private Decorator<IOSession> ioSessionDecorator;
70      private Callback<Exception> exceptionCallback;
71      private IOSessionListener sessionListener;
72      private H2StreamListener streamListener;
73  
74      private H2MultiplexingRequesterBootstrap() {
75          this.pushConsumerList = new ArrayList<>();
76      }
77  
78      public static H2MultiplexingRequesterBootstrap bootstrap() {
79          return new H2MultiplexingRequesterBootstrap();
80      }
81  
82      /**
83       * Sets I/O reactor configuration.
84       */
85      public final H2MultiplexingRequesterBootstrap setIOReactorConfig(final IOReactorConfig ioReactorConfig) {
86          this.ioReactorConfig = ioReactorConfig;
87          return this;
88      }
89  
90      /**
91       * Assigns {@link HttpProcessor} instance.
92       */
93      public final H2MultiplexingRequesterBootstrap setHttpProcessor(final HttpProcessor httpProcessor) {
94          this.httpProcessor = httpProcessor;
95          return this;
96      }
97  
98      /**
99       * Sets HTTP/2 protocol parameters
100      */
101     public final H2MultiplexingRequesterBootstrap setH2Config(final H2Config h2Config) {
102         this.h2Config = h2Config;
103         return this;
104     }
105 
106     /**
107      * Sets message char coding.
108      */
109     public final H2MultiplexingRequesterBootstrap setCharCodingConfig(final CharCodingConfig charCodingConfig) {
110         this.charCodingConfig = charCodingConfig;
111         return this;
112     }
113 
114     /**
115      * Assigns {@link TlsStrategy} instance.
116      */
117     public final H2MultiplexingRequesterBootstrap setTlsStrategy(final TlsStrategy tlsStrategy) {
118         this.tlsStrategy = tlsStrategy;
119         return this;
120     }
121 
122     public final H2MultiplexingRequesterBootstrap setStrictALPNHandshake(final boolean strictALPNHandshake) {
123         this.strictALPNHandshake = strictALPNHandshake;
124         return this;
125     }
126 
127     /**
128      * Assigns {@link IOSession} {@link Decorator} instance.
129      */
130     public final H2MultiplexingRequesterBootstrap setIOSessionDecorator(final Decorator<IOSession> ioSessionDecorator) {
131         this.ioSessionDecorator = ioSessionDecorator;
132         return this;
133     }
134 
135     /**
136      * Assigns {@link Exception} {@link Callback} instance.
137      */
138     public final H2MultiplexingRequesterBootstrap setExceptionCallback(final Callback<Exception> exceptionCallback) {
139         this.exceptionCallback = exceptionCallback;
140         return this;
141     }
142 
143     /**
144      * Assigns {@link IOSessionListener} instance.
145      */
146     public final H2MultiplexingRequesterBootstrap setIOSessionListener(final IOSessionListener sessionListener) {
147         this.sessionListener = sessionListener;
148         return this;
149     }
150 
151     /**
152      * Assigns {@link H2StreamListener} instance.
153      */
154     public final H2MultiplexingRequesterBootstrap setStreamListener(final H2StreamListener streamListener) {
155         this.streamListener = streamListener;
156         return this;
157     }
158 
159     /**
160      * Assigns {@link UriPatternType} for handler registration.
161      */
162     public final H2MultiplexingRequesterBootstrap setUriPatternType(final UriPatternType uriPatternType) {
163         this.uriPatternType = uriPatternType;
164         return this;
165     }
166 
167     /**
168      * Registers the given {@link AsyncPushConsumer} {@link Supplier} as a default handler for URIs
169      * matching the given pattern.
170      *
171      * @param uriPattern the pattern to register the handler for.
172      * @param supplier the handler supplier.
173      */
174     public final H2MultiplexingRequesterBootstrap register(final String uriPattern, final Supplier<AsyncPushConsumer> supplier) {
175         Args.notBlank(uriPattern, "URI pattern");
176         Args.notNull(supplier, "Supplier");
177         pushConsumerList.add(new HandlerEntry<>(null, uriPattern, supplier));
178         return this;
179     }
180 
181     /**
182      * Registers the given {@link AsyncPushConsumer} {@link Supplier} as a handler for URIs
183      * matching the given host and the pattern.
184      *
185      * @param hostname the host name
186      * @param uriPattern the pattern to register the handler for.
187      * @param supplier the handler supplier.
188      */
189     public final H2MultiplexingRequesterBootstrap registerVirtual(final String hostname, final String uriPattern, final Supplier<AsyncPushConsumer> supplier) {
190         Args.notBlank(hostname, "Hostname");
191         Args.notBlank(uriPattern, "URI pattern");
192         Args.notNull(supplier, "Supplier");
193         pushConsumerList.add(new HandlerEntry<>(hostname, uriPattern, supplier));
194         return this;
195     }
196 
197     public H2MultiplexingRequester create() {
198         final RequestHandlerRegistry<Supplier<AsyncPushConsumer>> registry = new RequestHandlerRegistry<>(uriPatternType);
199         for (final HandlerEntry<Supplier<AsyncPushConsumer>> entry: pushConsumerList) {
200             registry.register(entry.hostname, entry.uriPattern, entry.handler);
201         }
202         final ClientH2StreamMultiplexerFactory http2StreamHandlerFactory = new ClientH2StreamMultiplexerFactory(
203                 httpProcessor != null ? httpProcessor : H2Processors.client(),
204                 new DefaultAsyncPushConsumerFactory(registry),
205                 h2Config != null ? h2Config : H2Config.DEFAULT,
206                 charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
207                 streamListener);
208         return new H2MultiplexingRequester(
209                 ioReactorConfig,
210                 (ioSession, attachment) -> new ClientH2PrefaceHandler(ioSession, http2StreamHandlerFactory, strictALPNHandshake),
211                 ioSessionDecorator,
212                 exceptionCallback,
213                 sessionListener,
214                 DefaultAddressResolver.INSTANCE,
215                 tlsStrategy != null ? tlsStrategy : new H2ClientTlsStrategy());
216     }
217 
218 }