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.H2OnlyClientProtocolNegotiator;
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.IOEventHandler;
50  import org.apache.hc.core5.reactor.IOEventHandlerFactory;
51  import org.apache.hc.core5.reactor.IOReactorConfig;
52  import org.apache.hc.core5.reactor.IOSession;
53  import org.apache.hc.core5.reactor.IOSessionListener;
54  import org.apache.hc.core5.reactor.ProtocolIOSession;
55  import org.apache.hc.core5.util.Args;
56  
57  /**
58   * {@link H2MultiplexingRequester} bootstrap.
59   *
60   * @since 5.0
61   */
62  public class H2MultiplexingRequesterBootstrap {
63  
64      private final List<HandlerEntry<Supplier<AsyncPushConsumer>>> pushConsumerList;
65      private UriPatternType uriPatternType;
66      private IOReactorConfig ioReactorConfig;
67      private HttpProcessor httpProcessor;
68      private CharCodingConfig charCodingConfig;
69      private H2Config h2Config;
70      private TlsStrategy tlsStrategy;
71      private boolean strictALPNHandshake;
72      private Decorator<IOSession> ioSessionDecorator;
73      private Callback<Exception> exceptionCallback;
74      private IOSessionListener sessionListener;
75      private H2StreamListener streamListener;
76  
77      private H2MultiplexingRequesterBootstrap() {
78          this.pushConsumerList = new ArrayList<>();
79      }
80  
81      public static H2MultiplexingRequesterBootstrap bootstrap() {
82          return new H2MultiplexingRequesterBootstrap();
83      }
84  
85      /**
86       * Sets I/O reactor configuration.
87       */
88      public final H2MultiplexingRequesterBootstrap setIOReactorConfig(final IOReactorConfig ioReactorConfig) {
89          this.ioReactorConfig = ioReactorConfig;
90          return this;
91      }
92  
93      /**
94       * Assigns {@link HttpProcessor} instance.
95       */
96      public final H2MultiplexingRequesterBootstrap setHttpProcessor(final HttpProcessor httpProcessor) {
97          this.httpProcessor = httpProcessor;
98          return this;
99      }
100 
101     /**
102      * Sets HTTP/2 protocol parameters
103      */
104     public final H2MultiplexingRequesterBootstrap setH2Config(final H2Config h2Config) {
105         this.h2Config = h2Config;
106         return this;
107     }
108 
109     /**
110      * Sets message char coding.
111      */
112     public final H2MultiplexingRequesterBootstrap setCharCodingConfig(final CharCodingConfig charCodingConfig) {
113         this.charCodingConfig = charCodingConfig;
114         return this;
115     }
116 
117     /**
118      * Assigns {@link TlsStrategy} instance.
119      */
120     public final H2MultiplexingRequesterBootstrap setTlsStrategy(final TlsStrategy tlsStrategy) {
121         this.tlsStrategy = tlsStrategy;
122         return this;
123     }
124 
125     public final H2MultiplexingRequesterBootstrap setStrictALPNHandshake(final boolean strictALPNHandshake) {
126         this.strictALPNHandshake = strictALPNHandshake;
127         return this;
128     }
129 
130     /**
131      * Assigns {@link IOSession} {@link Decorator} instance.
132      */
133     public final H2MultiplexingRequesterBootstrap setIOSessionDecorator(final Decorator<IOSession> ioSessionDecorator) {
134         this.ioSessionDecorator = ioSessionDecorator;
135         return this;
136     }
137 
138     /**
139      * Assigns {@link Exception} {@link Callback} instance.
140      */
141     public final H2MultiplexingRequesterBootstrap setExceptionCallback(final Callback<Exception> exceptionCallback) {
142         this.exceptionCallback = exceptionCallback;
143         return this;
144     }
145 
146     /**
147      * Assigns {@link IOSessionListener} instance.
148      */
149     public final H2MultiplexingRequesterBootstrap setIOSessionListener(final IOSessionListener sessionListener) {
150         this.sessionListener = sessionListener;
151         return this;
152     }
153 
154     /**
155      * Assigns {@link H2StreamListener} instance.
156      */
157     public final H2MultiplexingRequesterBootstrap setStreamListener(final H2StreamListener streamListener) {
158         this.streamListener = streamListener;
159         return this;
160     }
161 
162     /**
163      * Assigns {@link UriPatternType} for handler registration.
164      */
165     public final H2MultiplexingRequesterBootstrap setUriPatternType(final UriPatternType uriPatternType) {
166         this.uriPatternType = uriPatternType;
167         return this;
168     }
169 
170     /**
171      * Registers the given {@link AsyncPushConsumer} {@link Supplier} as a default handler for URIs
172      * matching the given pattern.
173      *
174      * @param uriPattern the pattern to register the handler for.
175      * @param supplier the handler supplier.
176      */
177     public final H2MultiplexingRequesterBootstrap register(final String uriPattern, final Supplier<AsyncPushConsumer> supplier) {
178         Args.notBlank(uriPattern, "URI pattern");
179         Args.notNull(supplier, "Supplier");
180         pushConsumerList.add(new HandlerEntry<>(null, uriPattern, supplier));
181         return this;
182     }
183 
184     /**
185      * Registers the given {@link AsyncPushConsumer} {@link Supplier} as a handler for URIs
186      * matching the given host and the pattern.
187      *
188      * @param hostname the host name
189      * @param uriPattern the pattern to register the handler for.
190      * @param supplier the handler supplier.
191      */
192     public final H2MultiplexingRequesterBootstrap registerVirtual(final String hostname, final String uriPattern, final Supplier<AsyncPushConsumer> supplier) {
193         Args.notBlank(hostname, "Hostname");
194         Args.notBlank(uriPattern, "URI pattern");
195         Args.notNull(supplier, "Supplier");
196         pushConsumerList.add(new HandlerEntry<>(hostname, uriPattern, supplier));
197         return this;
198     }
199 
200     public H2MultiplexingRequester create() {
201         final RequestHandlerRegistry<Supplier<AsyncPushConsumer>> registry = new RequestHandlerRegistry<>(uriPatternType);
202         for (final HandlerEntry<Supplier<AsyncPushConsumer>> entry: pushConsumerList) {
203             registry.register(entry.hostname, entry.uriPattern, entry.handler);
204         }
205         final ClientH2StreamMultiplexerFactoryactory.html#ClientH2StreamMultiplexerFactory">ClientH2StreamMultiplexerFactory http2StreamHandlerFactory = new ClientH2StreamMultiplexerFactory(
206                 httpProcessor != null ? httpProcessor : H2Processors.client(),
207                 new DefaultAsyncPushConsumerFactory(registry),
208                 h2Config != null ? h2Config : H2Config.DEFAULT,
209                 charCodingConfig != null ? charCodingConfig : CharCodingConfig.DEFAULT,
210                 streamListener);
211         return new H2MultiplexingRequester(
212                 ioReactorConfig,
213                 new IOEventHandlerFactory() {
214 
215                     @Override
216                     public IOEventHandler createHandler(final ProtocolIOSession ioSession, final Object attachment) {
217                         return new H2OnlyClientProtocolNegotiator(ioSession, http2StreamHandlerFactory, strictALPNHandshake);
218                     }
219 
220                 },
221                 ioSessionDecorator,
222                 exceptionCallback,
223                 sessionListener,
224                 DefaultAddressResolver.INSTANCE,
225                 tlsStrategy != null ? tlsStrategy : new H2ClientTlsStrategy());
226     }
227 
228 }