001/* -*- mode: Java; c-basic-offset: 2; indent-tabs-mode: nil; coding: utf-8-unix -*-
002 *
003 * Copyright © 2019–2020 microBean™.
004 *
005 * Licensed under the Apache License, Version 2.0 (the "License");
006 * you may not use this file except in compliance with the License.
007 * You may obtain a copy of the License at
008 *
009 *     http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
014 * implied.  See the License for the specific language governing
015 * permissions and limitations under the License.
016 */
017package org.microbean.jersey.netty;
018
019import java.net.URI;
020
021import java.util.Objects;
022
023import java.util.function.Supplier;
024
025import javax.ws.rs.core.Application;
026import javax.ws.rs.core.Configuration;
027
028import io.netty.buffer.ByteBufAllocator;
029import io.netty.buffer.Unpooled;
030
031import io.netty.channel.Channel;
032import io.netty.channel.ChannelHandler; // for javadoc only
033import io.netty.channel.ChannelHandlerContext;
034import io.netty.channel.ChannelInitializer;
035import io.netty.channel.ChannelPipeline;
036import io.netty.channel.SimpleChannelInboundHandler;
037
038import io.netty.util.concurrent.DefaultEventExecutorGroup;
039import io.netty.util.concurrent.EventExecutorGroup;
040
041import io.netty.handler.codec.http.HttpMessage;
042import io.netty.handler.codec.http.HttpRequest;
043import io.netty.handler.codec.http.HttpServerCodec;
044import io.netty.handler.codec.http.HttpServerExpectContinueHandler;
045import io.netty.handler.codec.http.HttpServerUpgradeHandler;
046import io.netty.handler.codec.http.HttpServerUpgradeHandler.SourceCodec; // for javadoc only
047import io.netty.handler.codec.http.HttpServerUpgradeHandler.UpgradeCodec;
048import io.netty.handler.codec.http.HttpServerUpgradeHandler.UpgradeCodecFactory;
049
050import io.netty.handler.codec.http2.CleartextHttp2ServerUpgradeHandler;
051import io.netty.handler.codec.http2.Http2CodecUtil;
052import io.netty.handler.codec.http2.Http2FrameCodec;
053import io.netty.handler.codec.http2.Http2FrameCodecBuilder;
054import io.netty.handler.codec.http2.Http2HeadersFrame;
055import io.netty.handler.codec.http2.Http2MultiplexHandler;
056import io.netty.handler.codec.http2.Http2ServerUpgradeCodec;
057
058import io.netty.handler.ssl.ApplicationProtocolNames;
059import io.netty.handler.ssl.ApplicationProtocolNegotiationHandler;
060import io.netty.handler.ssl.SslContext;
061import io.netty.handler.ssl.SslHandler;
062
063import io.netty.util.AsciiString;
064import io.netty.util.ReferenceCountUtil;
065
066import org.glassfish.jersey.internal.inject.Bindings;
067import org.glassfish.jersey.internal.inject.InjectionManager;
068import org.glassfish.jersey.internal.inject.ReferencingFactory;
069
070import org.glassfish.jersey.process.internal.RequestScoped;
071
072import org.glassfish.jersey.server.ApplicationHandler;
073import org.glassfish.jersey.server.ContainerRequest; // for javadoc only
074
075import org.microbean.jersey.netty.AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator;
076
077/**
078 * A {@link ChannelInitializer} that {@linkplain
079 * #initChannel(Channel) initializes
080 * <code>Channel</code>s} by configuring their {@link
081 * ChannelPipeline}s to include {@link ChannelHandler}s that transform
082 * Netty HTTP and HTTP/2 messages into Jersey {@link
083 * ContainerRequest}s that are then {@linkplain
084 * ApplicationHandler#handle(ContainerRequest) handled} by an {@link
085 * ApplicationHandler}.
086 *
087 * @author <a href="https://about.me/lairdnelson"
088 * target="_parent">Laird Nelson</a>
089 *
090 * @see #initChannel(Channel)
091 *
092 * @see ContainerRequest
093 *
094 * @see ApplicationHandler#handle(ContainerRequest)
095 *
096 * @see HttpObjectToContainerRequestDecoder
097 *
098 * @see HttpContainerRequestHandlingResponseWriter
099 *
100 * @see Http2StreamFrameToContainerRequestDecoder
101 *
102 * @see Http2ContainerRequestHandlingResponseWriter
103 */
104public class JerseyChannelInitializer extends ChannelInitializer<Channel> {
105
106
107  /*
108   * Static fields.
109   */
110
111
112  /*
113   * Instance fields.
114   */
115
116
117  /**
118   * The base {@link URI} for the Jersey application.
119   *
120   * <p>This field is never {@code null}.</p>
121   *
122   * @see #JerseyChannelInitializer(URI, SslContext, long,
123   * ApplicationHandler)
124   */
125  private final URI baseUri;
126
127  /**
128   * An {@link SslContext} that may be used to {@linkplain
129   * #createSslHandler(SslContext, ByteBufAllocator) create an
130   * <code>SslHandler</code>}.
131   *
132   * <p>This field may be {@code null}.</p>
133   *
134   * @see #JerseyChannelInitializer(URI, SslContext, long,
135   * ApplicationHandler)
136   *
137   * @see SslContext
138   *
139   * @see #createSslHandler(SslContext, ByteBufAllocator)
140   */
141  private final SslContext sslContext;
142
143  private final boolean http2Support;
144
145  /**
146   * In the case of HTTP to HTTP/2
147   * upgrades, this field governs the maximum permitted incoming
148   * entity length in bytes; if less than {@code 0} then {@link
149   * Long#MAX_VALUE} will be used instead; if exactly {@code 0} then
150   * if the HTTP message containing the upgrade header is something
151   * like a {@code POST} it will be rejected with a {@code 413} error
152   * code.
153   *
154   * @see HttpServerUpgradeHandler#maxContentLength()
155   */
156  private final long maxIncomingContentLength;
157
158  private final EventExecutorGroup jerseyEventExecutorGroup;
159
160  private final Supplier<? extends ApplicationHandler> applicationHandlerSupplier;
161
162  private final int flushThreshold;
163
164  private final ByteBufCreator byteBufCreator;
165
166
167  /*
168   * Constructors.
169   */
170
171
172  /**
173   * Creates a new {@link JerseyChannelInitializer}.
174   *
175   * @param baseUri a {@link URI} that will serve as the {@linkplain
176   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
177   * {@link ContainerRequest}; may be {@code null} in which case the
178   * return value of {@link URI#create(String) URI.create("/")} will
179   * be used instead
180   *
181   * @param sslContext an {@link SslContext}; may be {@code null} in
182   * which case network communications will occur in plain text
183   *
184   * @param jaxrsApplication the {@link Application} to run; may be
185   * {@code null} somewhat pathologically
186   *
187   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
188   * EventExecutorGroup, boolean, Supplier, int,
189   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
190   *
191   * @see ContainerRequest
192   *
193   * @see SslContext
194   *
195   * @see
196   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
197   * UpgradeCodecFactory, int)
198   *
199   * @see ApplicationHandler#handle(ContainerRequest)
200   *
201   * @see AbstractContainerRequestHandlingResponseWriter
202   *
203   * @see HttpObjectToContainerRequestDecoder
204   *
205   * @see HttpContainerRequestHandlingResponseWriter
206   *
207   * @see Http2StreamFrameToContainerRequestDecoder
208   *
209   * @see Http2ContainerRequestHandlingResponseWriter
210   */
211  public JerseyChannelInitializer(final URI baseUri,
212                                  final SslContext sslContext,
213                                  final Application jaxrsApplication) {
214    this(baseUri,
215         sslContext,
216         true,
217         toApplicationHandlerSupplier(jaxrsApplication));
218  }
219
220  /**
221   * Creates a new {@link JerseyChannelInitializer}.
222   *
223   * @param baseUri a {@link URI} that will serve as the {@linkplain
224   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
225   * {@link ContainerRequest}; may be {@code null} in which case the
226   * return value of {@link URI#create(String) URI.create("/")} will
227   * be used instead
228   *
229   * @param sslContext an {@link SslContext}; may be {@code null} in
230   * which case network communications will occur in plain text
231   *
232   * @param applicationHandler an {@link ApplicationHandler}
233   * representing a <a
234   * href="https://jakarta.ee/specifications/restful-ws/"
235   * target="_parent">Jakarta RESTful Web Services application</a>
236   * whose {@link ApplicationHandler#handle(ContainerRequest)} method
237   * will serve as the bridge between Netty and Jersey; may be {@code
238   * null} somewhat pathologically but normally is not
239   *
240   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
241   * EventExecutorGroup, boolean, Supplier, int,
242   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
243   *
244   * @see ContainerRequest
245   *
246   * @see SslContext
247   *
248   * @see
249   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
250   * UpgradeCodecFactory, int)
251   *
252   * @see ApplicationHandler#handle(ContainerRequest)
253   *
254   * @see AbstractContainerRequestHandlingResponseWriter
255   *
256   * @see HttpObjectToContainerRequestDecoder
257   *
258   * @see HttpContainerRequestHandlingResponseWriter
259   *
260   * @see Http2StreamFrameToContainerRequestDecoder
261   *
262   * @see Http2ContainerRequestHandlingResponseWriter
263   */
264  public JerseyChannelInitializer(final URI baseUri,
265                                  final SslContext sslContext,
266                                  final ApplicationHandler applicationHandler) {
267    this(baseUri,
268         sslContext,
269         true,
270         toApplicationHandlerSupplier(applicationHandler));
271  }
272
273  /**
274   * Creates a new {@link JerseyChannelInitializer}.
275   *
276   * @param baseUri a {@link URI} that will serve as the {@linkplain
277   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
278   * {@link ContainerRequest}; may be {@code null} in which case the
279   * return value of {@link URI#create(String) URI.create("/")} will
280   * be used instead
281   *
282   * @param sslContext an {@link SslContext}; may be {@code null} in
283   * which case network communications will occur in plain text
284   *
285   * @param applicationHandlerSupplier a {@link Supplier} of an {@link
286   * ApplicationHandler} representing a <a
287   * href="https://jakarta.ee/specifications/restful-ws/"
288   * target="_parent">Jakarta RESTful Web Services application</a>
289   * whose {@link ApplicationHandler#handle(ContainerRequest)} method
290   * will serve as the bridge between Netty and Jersey; may be {@code
291   * null} somewhat pathologically but normally is not
292   *
293   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
294   * EventExecutorGroup, boolean, Supplier, int,
295   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
296   *
297   * @see ContainerRequest
298   *
299   * @see SslContext
300   *
301   * @see
302   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
303   * UpgradeCodecFactory, int)
304   *
305   * @see ApplicationHandler#handle(ContainerRequest)
306   *
307   * @see AbstractContainerRequestHandlingResponseWriter
308   *
309   * @see HttpObjectToContainerRequestDecoder
310   *
311   * @see HttpContainerRequestHandlingResponseWriter
312   *
313   * @see Http2StreamFrameToContainerRequestDecoder
314   *
315   * @see Http2ContainerRequestHandlingResponseWriter
316   */
317  public JerseyChannelInitializer(final URI baseUri,
318                                  final SslContext sslContext,
319                                  final Supplier<? extends ApplicationHandler> applicationHandlerSupplier) {
320    this(baseUri,
321         sslContext,
322         true,
323         applicationHandlerSupplier);
324  }
325
326  /**
327   * Creates a new {@link JerseyChannelInitializer}.
328   *
329   * @param baseUri a {@link URI} that will serve as the {@linkplain
330   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
331   * {@link ContainerRequest}; may be {@code null} in which case the
332   * return value of {@link URI#create(String) URI.create("/")} will
333   * be used instead
334   *
335   * @param sslContext an {@link SslContext}; may be {@code null} in
336   * which case network communications will occur in plain text
337   *
338   * @param http2Support if HTTP/2 support (including upgrades, prior
339   * knowledge, h2c, etc.) should be enabled
340   *
341   * @param jaxrsApplication the {@link Application} to run; may be
342   * {@code null} somewhat pathologically
343   *
344   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
345   * EventExecutorGroup, boolean, Supplier, int,
346   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
347   *
348   * @see ContainerRequest
349   *
350   * @see SslContext
351   *
352   * @see
353   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
354   * UpgradeCodecFactory, int)
355   *
356   * @see ApplicationHandler#handle(ContainerRequest)
357   *
358   * @see AbstractContainerRequestHandlingResponseWriter
359   *
360   * @see HttpObjectToContainerRequestDecoder
361   *
362   * @see HttpContainerRequestHandlingResponseWriter
363   *
364   * @see Http2StreamFrameToContainerRequestDecoder
365   *
366   * @see Http2ContainerRequestHandlingResponseWriter
367   */
368  public JerseyChannelInitializer(final URI baseUri,
369                                  final SslContext sslContext,
370                                  final boolean http2Support,
371                                  final Application jaxrsApplication) {
372    this(baseUri,
373         sslContext,
374         http2Support,
375         20971520L, /* 20 MB; arbitrary */
376         null, /* Jersey EventExecutorGroup will be defaulted */
377         true, /* use Jersey injection */
378         toApplicationHandlerSupplier(jaxrsApplication),
379         8192, /* 8K; arbitrary */
380         Unpooled::wrappedBuffer);
381  }
382
383  /**
384   * Creates a new {@link JerseyChannelInitializer}.
385   *
386   * @param baseUri a {@link URI} that will serve as the {@linkplain
387   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
388   * {@link ContainerRequest}; may be {@code null} in which case the
389   * return value of {@link URI#create(String) URI.create("/")} will
390   * be used instead
391   *
392   * @param sslContext an {@link SslContext}; may be {@code null} in
393   * which case network communications will occur in plain text
394   *
395   * @param http2Support if HTTP/2 support (including upgrades, prior
396   * knowledge, h2c, etc.) should be enabled
397   *
398   * @param applicationHandler an {@link ApplicationHandler}
399   * representing a <a
400   * href="https://jakarta.ee/specifications/restful-ws/"
401   * target="_parent">Jakarta RESTful Web Services application</a>
402   * whose {@link ApplicationHandler#handle(ContainerRequest)} method
403   * will serve as the bridge between Netty and Jersey; may be {@code
404   * null} somewhat pathologically but normally is not
405   *
406   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
407   * EventExecutorGroup, boolean, Supplier, int,
408   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
409   *
410   * @see ContainerRequest
411   *
412   * @see SslContext
413   *
414   * @see
415   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
416   * UpgradeCodecFactory, int)
417   *
418   * @see ApplicationHandler#handle(ContainerRequest)
419   *
420   * @see AbstractContainerRequestHandlingResponseWriter
421   *
422   * @see HttpObjectToContainerRequestDecoder
423   *
424   * @see HttpContainerRequestHandlingResponseWriter
425   *
426   * @see Http2StreamFrameToContainerRequestDecoder
427   *
428   * @see Http2ContainerRequestHandlingResponseWriter
429   */
430  public JerseyChannelInitializer(final URI baseUri,
431                                  final SslContext sslContext,
432                                  final boolean http2Support,
433                                  final ApplicationHandler applicationHandler) {
434    this(baseUri,
435         sslContext,
436         http2Support,
437         20971520L, /* 20 MB; arbitrary */
438         null, /* Jersey EventExecutorGroup will be defaulted */
439         true, /* use Jersey injection */
440         toApplicationHandlerSupplier(applicationHandler),
441         8192, /* 8K; arbitrary */
442         Unpooled::wrappedBuffer);
443  }
444
445  /**
446   * Creates a new {@link JerseyChannelInitializer}.
447   *
448   * @param baseUri a {@link URI} that will serve as the {@linkplain
449   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
450   * {@link ContainerRequest}; may be {@code null} in which case the
451   * return value of {@link URI#create(String) URI.create("/")} will
452   * be used instead
453   *
454   * @param sslContext an {@link SslContext}; may be {@code null} in
455   * which case network communications will occur in plain text
456   *
457   * @param http2Support if HTTP/2 support (including upgrades, prior
458   * knowledge, h2c, etc.) should be enabled
459   *
460   * @param applicationHandlerSupplier a {@link Supplier} of an {@link
461   * ApplicationHandler} representing a <a
462   * href="https://jakarta.ee/specifications/restful-ws/"
463   * target="_parent">Jakarta RESTful Web Services application</a>
464   * whose {@link ApplicationHandler#handle(ContainerRequest)} method
465   * will serve as the bridge between Netty and Jersey; may be {@code
466   * null} somewhat pathologically but normally is not
467   *
468   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
469   * EventExecutorGroup, boolean, Supplier, int,
470   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
471   *
472   * @see ContainerRequest
473   *
474   * @see SslContext
475   *
476   * @see
477   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
478   * UpgradeCodecFactory, int)
479   *
480   * @see ApplicationHandler#handle(ContainerRequest)
481   *
482   * @see AbstractContainerRequestHandlingResponseWriter
483   *
484   * @see HttpObjectToContainerRequestDecoder
485   *
486   * @see HttpContainerRequestHandlingResponseWriter
487   *
488   * @see Http2StreamFrameToContainerRequestDecoder
489   *
490   * @see Http2ContainerRequestHandlingResponseWriter
491   */
492  public JerseyChannelInitializer(final URI baseUri,
493                                  final SslContext sslContext,
494                                  final boolean http2Support,
495                                  final Supplier<? extends ApplicationHandler> applicationHandlerSupplier) {
496    this(baseUri,
497         sslContext,
498         http2Support,
499         20971520L, /* 20 MB; arbitrary */
500         null, /* Jersey EventExecutorGroup will be defaulted */
501         true, /* use Jersey injection */
502         applicationHandlerSupplier,
503         8192, /* 8K; arbitrary */
504         Unpooled::wrappedBuffer);
505  }
506
507  /**
508   * Creates a new {@link JerseyChannelInitializer}.
509   *
510   * @param baseUri a {@link URI} that will serve as the {@linkplain
511   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
512   * {@link ContainerRequest}; may be {@code null} in which case the
513   * return value of {@link URI#create(String) URI.create("/")} will
514   * be used instead
515   *
516   * @param sslContext an {@link SslContext}; may be {@code null} in
517   * which case network communications will occur in plain text
518   *
519   * @param http2Support if HTTP/2 support (including upgrades, prior
520   * knowledge, h2c, etc.) should be enabled
521   *
522   * @param maxIncomingContentLength in the case of HTTP to HTTP/2
523   * upgrades, a {@code long} that governs the maximum permitted
524   * incoming entity length in bytes; if less than {@code 0} then
525   * {@link Long#MAX_VALUE} will be used instead; if exactly {@code 0}
526   * then if the HTTP message containing the upgrade header is
527   * something like a {@code POST} it will be rejected with a {@code
528   * 413} error code; ignored entirely if {@code http2Support} is
529   * {@code false}
530   *
531   * @param jerseyEventExecutorGroup an {@link EventExecutorGroup}
532   * that will manage the thread on which an {@link
533   * ApplicationHandler#handle(ContainerRequest)} call will occur; may
534   * be {@code null} in which case a new {@link
535   * DefaultEventExecutorGroup} will be used instead
536   *
537   * @param jaxrsApplication the {@link Application} to run; may be
538   * {@code null} somewhat pathologically
539   *
540   * @param flushThreshold the minimum number of bytes that an {@link
541   * AbstractByteBufBackedChannelOutboundInvokingOutputStream}
542   * returned by an implementation of the {@link
543   * AbstractContainerRequestHandlingResponseWriter#createOutputStream(long,
544   * ContainerResponse)} method must write before an automatic
545   * {@linkplain
546   * AbstractByteBufBackedChannelOutboundInvokingOutputStream#flush()
547   * flush} may take place; if less than {@code 0} {@code 0} will be
548   * used instead; if {@link Integer#MAX_VALUE} then it is suggested
549   * that no automatic flushing will occur
550   *
551   * @param byteBufCreator a {@link ByteBufCreator} that will be
552   * {@linkplain
553   * AbstractContainerRequestHandlingResponseWriter#AbstractContainerRequestHandlingResponseWriter(Supplier,
554   * int,
555   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
556   * passed to an
557   * <code>AbstractContainerRequestHandlingResponseWriter</code>}
558   * implementation; may be {@code null}
559   *
560   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
561   * EventExecutorGroup, boolean, Supplier, int,
562   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
563   *
564   * @see ContainerRequest
565   *
566   * @see SslContext
567   *
568   * @see
569   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
570   * UpgradeCodecFactory, int)
571   *
572   * @see ApplicationHandler#handle(ContainerRequest)
573   *
574   * @see AbstractContainerRequestHandlingResponseWriter
575   *
576   * @see HttpObjectToContainerRequestDecoder
577   *
578   * @see HttpContainerRequestHandlingResponseWriter
579   *
580   * @see Http2StreamFrameToContainerRequestDecoder
581   *
582   * @see Http2ContainerRequestHandlingResponseWriter
583   */
584  public JerseyChannelInitializer(final URI baseUri,
585                                  final SslContext sslContext,
586                                  final boolean http2Support,
587                                  final long maxIncomingContentLength,
588                                  final EventExecutorGroup jerseyEventExecutorGroup,
589                                  final Application jaxrsApplication,
590                                  final int flushThreshold,
591                                  final ByteBufCreator byteBufCreator) {
592    this(baseUri,
593         sslContext,
594         http2Support,
595         maxIncomingContentLength,
596         jerseyEventExecutorGroup,
597         true, /* use Jersey injection */
598         toApplicationHandlerSupplier(jaxrsApplication),
599         flushThreshold,
600         byteBufCreator);
601  }
602
603  /**
604   * Creates a new {@link JerseyChannelInitializer}.
605   *
606   * @param baseUri a {@link URI} that will serve as the {@linkplain
607   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
608   * {@link ContainerRequest}; may be {@code null} in which case the
609   * return value of {@link URI#create(String) URI.create("/")} will
610   * be used instead
611   *
612   * @param sslContext an {@link SslContext}; may be {@code null} in
613   * which case network communications will occur in plain text
614   *
615   * @param http2Support if HTTP/2 support (including upgrades, prior
616   * knowledge, h2c, etc.) should be enabled
617   *
618   * @param maxIncomingContentLength in the case of HTTP to HTTP/2
619   * upgrades, a {@code long} that governs the maximum permitted
620   * incoming entity length in bytes; if less than {@code 0} then
621   * {@link Long#MAX_VALUE} will be used instead; if exactly {@code 0}
622   * then if the HTTP message containing the upgrade header is
623   * something like a {@code POST} it will be rejected with a {@code
624   * 413} error code; ignored entirely if {@code http2Support} is
625   * {@code false}
626   *
627   * @param jerseyEventExecutorGroup an {@link EventExecutorGroup}
628   * that will manage the thread on which an {@link
629   * ApplicationHandler#handle(ContainerRequest)} call will occur; may
630   * be {@code null} in which case a new {@link
631   * DefaultEventExecutorGroup} will be used instead
632   *
633   * @param applicationHandler an {@link ApplicationHandler}
634   * representing a <a
635   * href="https://jakarta.ee/specifications/restful-ws/"
636   * target="_parent">Jakarta RESTful Web Services application</a>
637   * whose {@link ApplicationHandler#handle(ContainerRequest)} method
638   * will serve as the bridge between Netty and Jersey; may be {@code
639   * null} somewhat pathologically but normally is not
640   *
641   * @param flushThreshold the minimum number of bytes that an {@link
642   * AbstractByteBufBackedChannelOutboundInvokingOutputStream}
643   * returned by an implementation of the {@link
644   * AbstractContainerRequestHandlingResponseWriter#createOutputStream(long,
645   * ContainerResponse)} method must write before an automatic
646   * {@linkplain
647   * AbstractByteBufBackedChannelOutboundInvokingOutputStream#flush()
648   * flush} may take place; if less than {@code 0} {@code 0} will be
649   * used instead; if {@link Integer#MAX_VALUE} then it is suggested
650   * that no automatic flushing will occur
651   *
652   * @param byteBufCreator a {@link ByteBufCreator} that will be
653   * {@linkplain
654   * AbstractContainerRequestHandlingResponseWriter#AbstractContainerRequestHandlingResponseWriter(Supplier,
655   * int,
656   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
657   * passed to an
658   * <code>AbstractContainerRequestHandlingResponseWriter</code>}
659   * implementation; may be {@code null}
660   *
661   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
662   * EventExecutorGroup, boolean, ApplicationHandler, int,
663   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
664   * @see ContainerRequest
665   *
666   * @see SslContext
667   *
668   * @see
669   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
670   * UpgradeCodecFactory, int)
671   *
672   * @see ApplicationHandler#handle(ContainerRequest)
673   *
674   * @see AbstractContainerRequestHandlingResponseWriter
675   *
676   * @see HttpObjectToContainerRequestDecoder
677   *
678   * @see HttpContainerRequestHandlingResponseWriter
679   *
680   * @see Http2StreamFrameToContainerRequestDecoder
681   *
682   * @see Http2ContainerRequestHandlingResponseWriter
683   */
684  public JerseyChannelInitializer(final URI baseUri,
685                                  final SslContext sslContext,
686                                  final boolean http2Support,
687                                  final long maxIncomingContentLength,
688                                  final EventExecutorGroup jerseyEventExecutorGroup,
689                                  final ApplicationHandler applicationHandler,
690                                  final int flushThreshold,
691                                  final ByteBufCreator byteBufCreator) {
692    this(baseUri,
693         sslContext,
694         http2Support,
695         maxIncomingContentLength,
696         jerseyEventExecutorGroup,
697         true, /* use Jersey injection */
698         toApplicationHandlerSupplier(applicationHandler),
699         flushThreshold,
700         byteBufCreator);
701  }
702
703  /**
704   * Creates a new {@link JerseyChannelInitializer}.
705   *
706   * @param baseUri a {@link URI} that will serve as the {@linkplain
707   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
708   * {@link ContainerRequest}; may be {@code null} in which case the
709   * return value of {@link URI#create(String) URI.create("/")} will
710   * be used instead
711   *
712   * @param sslContext an {@link SslContext}; may be {@code null} in
713   * which case network communications will occur in plain text
714   *
715   * @param http2Support if HTTP/2 support (including upgrades, prior
716   * knowledge, h2c, etc.) should be enabled
717   *
718   * @param maxIncomingContentLength in the case of HTTP to HTTP/2
719   * upgrades, a {@code long} that governs the maximum permitted
720   * incoming entity length in bytes; if less than {@code 0} then
721   * {@link Long#MAX_VALUE} will be used instead; if exactly {@code 0}
722   * then if the HTTP message containing the upgrade header is
723   * something like a {@code POST} it will be rejected with a {@code
724   * 413} error code; ignored entirely if {@code http2Support} is
725   * {@code false}
726   *
727   * @param jerseyEventExecutorGroup an {@link EventExecutorGroup}
728   * that will manage the thread on which an {@link
729   * ApplicationHandler#handle(ContainerRequest)} call will occur; may
730   * be {@code null} in which case a new {@link
731   * DefaultEventExecutorGroup} will be used instead
732   *
733   * @param applicationHandlerSupplier a {@link Supplier} of an {@link
734   * ApplicationHandler} representing a <a
735   * href="https://jakarta.ee/specifications/restful-ws/"
736   * target="_parent">Jakarta RESTful Web Services application</a>
737   * whose {@link ApplicationHandler#handle(ContainerRequest)} method
738   * will serve as the bridge between Netty and Jersey; may be {@code
739   * null} somewhat pathologically but normally is not
740   *
741   * @param flushThreshold the minimum number of bytes that an {@link
742   * AbstractByteBufBackedChannelOutboundInvokingOutputStream}
743   * returned by an implementation of the {@link
744   * AbstractContainerRequestHandlingResponseWriter#createOutputStream(long,
745   * ContainerResponse)} method must write before an automatic
746   * {@linkplain
747   * AbstractByteBufBackedChannelOutboundInvokingOutputStream#flush()
748   * flush} may take place; if less than {@code 0} {@code 0} will be
749   * used instead; if {@link Integer#MAX_VALUE} then it is suggested
750   * that no automatic flushing will occur
751   *
752   * @param byteBufCreator a {@link ByteBufCreator} that will be
753   * {@linkplain
754   * AbstractContainerRequestHandlingResponseWriter#AbstractContainerRequestHandlingResponseWriter(Supplier,
755   * int,
756   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
757   * passed to an
758   * <code>AbstractContainerRequestHandlingResponseWriter</code>}
759   * implementation; may be {@code null}
760   *
761   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
762   * EventExecutorGroup, boolean, Supplier, int,
763   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
764   * @see ContainerRequest
765   *
766   * @see SslContext
767   *
768   * @see
769   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
770   * UpgradeCodecFactory, int)
771   *
772   * @see ApplicationHandler#handle(ContainerRequest)
773   *
774   * @see AbstractContainerRequestHandlingResponseWriter
775   *
776   * @see HttpObjectToContainerRequestDecoder
777   *
778   * @see HttpContainerRequestHandlingResponseWriter
779   *
780   * @see Http2StreamFrameToContainerRequestDecoder
781   *
782   * @see Http2ContainerRequestHandlingResponseWriter
783   */
784  public JerseyChannelInitializer(final URI baseUri,
785                                  final SslContext sslContext,
786                                  final boolean http2Support,
787                                  final long maxIncomingContentLength,
788                                  final EventExecutorGroup jerseyEventExecutorGroup,
789                                  final Supplier<? extends ApplicationHandler> applicationHandlerSupplier,
790                                  final int flushThreshold,
791                                  final ByteBufCreator byteBufCreator) {
792    this(baseUri,
793         sslContext,
794         http2Support,
795         maxIncomingContentLength,
796         jerseyEventExecutorGroup,
797         true, /* use Jersey injection */
798         applicationHandlerSupplier,
799         flushThreshold,
800         byteBufCreator);
801  }
802
803  /**
804   * Creates a new {@link JerseyChannelInitializer}.
805   *
806   * @param baseUri a {@link URI} that will serve as the {@linkplain
807   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
808   * {@link ContainerRequest}; may be {@code null} in which case the
809   * return value of {@link URI#create(String) URI.create("/")} will
810   * be used instead
811   *
812   * @param sslContext an {@link SslContext}; may be {@code null} in
813   * which case network communications will occur in plain text
814   *
815   * @param http2Support if HTTP/2 support (including upgrades, prior
816   * knowledge, h2c, etc.) should be enabled
817   *
818   * @param maxIncomingContentLength in the case of HTTP to HTTP/2
819   * upgrades, a {@code long} that governs the maximum permitted
820   * incoming entity length in bytes; if less than {@code 0} then
821   * {@link Long#MAX_VALUE} will be used instead; if exactly {@code 0}
822   * then if the HTTP message containing the upgrade header is
823   * something like a {@code POST} it will be rejected with a {@code
824   * 413} error code; ignored entirely if {@code http2Support} is
825   * {@code false}
826   *
827   * @param jerseyEventExecutorGroup an {@link EventExecutorGroup}
828   * that will manage the thread on which an {@link
829   * ApplicationHandler#handle(ContainerRequest)} call will occur; may
830   * be {@code null} in which case a new {@link
831   * DefaultEventExecutorGroup} will be used instead
832   *
833   * @param useJerseyInjection if {@code true} then certain Netty
834   * constructs like {@link ChannelHandlerContext} will be made
835   * available for dependency injection in user applications using
836   * Jersey's native dependency injection facilities; if {@code false}
837   * then these facilities will not be used or referenced
838   *
839   * @param applicationHandler an {@link ApplicationHandler}
840   * representing a <a
841   * href="https://jakarta.ee/specifications/restful-ws/"
842   * target="_parent">Jakarta RESTful Web Services application</a>
843   * whose {@link ApplicationHandler#handle(ContainerRequest)} method
844   * will serve as the bridge between Netty and Jersey; may be {@code
845   * null} somewhat pathologically but normally is not
846   *
847   * @param flushThreshold the minimum number of bytes that an {@link
848   * AbstractByteBufBackedChannelOutboundInvokingOutputStream}
849   * returned by an implementation of the {@link
850   * AbstractContainerRequestHandlingResponseWriter#createOutputStream(long,
851   * ContainerResponse)} method must write before an automatic
852   * {@linkplain
853   * AbstractByteBufBackedChannelOutboundInvokingOutputStream#flush()
854   * flush} may take place; if less than {@code 0} {@code 0} will be
855   * used instead; if {@link Integer#MAX_VALUE} then it is suggested
856   * that no automatic flushing will occur
857   *
858   * @param byteBufCreator a {@link ByteBufCreator} that will be
859   * {@linkplain
860   * AbstractContainerRequestHandlingResponseWriter#AbstractContainerRequestHandlingResponseWriter(Supplier,
861   * int,
862   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
863   * passed to an
864   * <code>AbstractContainerRequestHandlingResponseWriter</code>}
865   * implementation; may be {@code null}
866   *
867   * @see ContainerRequest
868   *
869   * @see SslContext
870   *
871   * @see
872   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
873   * UpgradeCodecFactory, int)
874   *
875   * @see ApplicationHandler#handle(ContainerRequest)
876   *
877   * @see AbstractContainerRequestHandlingResponseWriter
878   *
879   * @see HttpObjectToContainerRequestDecoder
880   *
881   * @see HttpContainerRequestHandlingResponseWriter
882   *
883   * @see Http2StreamFrameToContainerRequestDecoder
884   *
885   * @see Http2ContainerRequestHandlingResponseWriter
886   */
887  public JerseyChannelInitializer(final URI baseUri,
888                                  final SslContext sslContext,
889                                  final boolean http2Support,
890                                  final long maxIncomingContentLength,
891                                  final EventExecutorGroup jerseyEventExecutorGroup,
892                                  final boolean useJerseyInjection,
893                                  final ApplicationHandler applicationHandler,
894                                  final int flushThreshold,
895                                  final ByteBufCreator byteBufCreator) {
896    this(baseUri,
897         sslContext,
898         http2Support,
899         maxIncomingContentLength,
900         jerseyEventExecutorGroup,
901         useJerseyInjection,
902         toApplicationHandlerSupplier(applicationHandler),
903         flushThreshold,
904         byteBufCreator);
905  }
906
907  /**
908   * Creates a new {@link JerseyChannelInitializer}.
909   *
910   * @param baseUri a {@link URI} that will serve as the {@linkplain
911   * ContainerRequest#getBaseUri() base <code>URI</code>} in a new
912   * {@link ContainerRequest}; may be {@code null} in which case the
913   * return value of {@link URI#create(String) URI.create("/")} will
914   * be used instead
915   *
916   * @param sslContext an {@link SslContext}; may be {@code null} in
917   * which case network communications will occur in plain text
918   *
919   * @param http2Support if HTTP/2 support (including upgrades, prior
920   * knowledge, h2c, etc.) should be enabled
921   *
922   * @param maxIncomingContentLength in the case of HTTP to HTTP/2
923   * upgrades, a {@code long} that governs the maximum permitted
924   * incoming entity length in bytes; if less than {@code 0} then
925   * {@link Long#MAX_VALUE} will be used instead; if exactly {@code 0}
926   * then if the HTTP message containing the upgrade header is
927   * something like a {@code POST} it will be rejected with a {@code
928   * 413} error code; ignored entirely if {@code http2Support} is
929   * {@code false}
930   *
931   * @param jerseyEventExecutorGroup an {@link EventExecutorGroup}
932   * that will manage the thread on which an {@link
933   * ApplicationHandler#handle(ContainerRequest)} call will occur; may
934   * be {@code null} in which case a new {@link
935   * DefaultEventExecutorGroup} will be used instead
936   *
937   * @param useJerseyInjection if {@code true} then certain Netty
938   * constructs like {@link ChannelHandlerContext} will be made
939   * available for dependency injection in user applications using
940   * Jersey's native dependency injection facilities; if {@code false}
941   * then these facilities will not be used or referenced
942   *
943   * @param applicationHandlerSupplier a {@link Supplier} of an {@link
944   * ApplicationHandler} representing a <a
945   * href="https://jakarta.ee/specifications/restful-ws/"
946   * target="_parent">Jakarta RESTful Web Services application</a>
947   * whose {@link ApplicationHandler#handle(ContainerRequest)} method
948   * will serve as the bridge between Netty and Jersey; may be {@code
949   * null} somewhat pathologically but normally is not.
950   *
951   * @param flushThreshold the minimum number of bytes that an {@link
952   * AbstractByteBufBackedChannelOutboundInvokingOutputStream}
953   * returned by an implementation of the {@link
954   * AbstractContainerRequestHandlingResponseWriter#createOutputStream(long,
955   * ContainerResponse)} method must write before an automatic
956   * {@linkplain
957   * AbstractByteBufBackedChannelOutboundInvokingOutputStream#flush()
958   * flush} may take place; if less than {@code 0} {@code 0} will be
959   * used instead; if {@link Integer#MAX_VALUE} then it is suggested
960   * that no automatic flushing will occur
961   *
962   * @param byteBufCreator a {@link ByteBufCreator} that will be
963   * {@linkplain
964   * AbstractContainerRequestHandlingResponseWriter#AbstractContainerRequestHandlingResponseWriter(Supplier,
965   * int,
966   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
967   * passed to an
968   * <code>AbstractContainerRequestHandlingResponseWriter</code>}
969   * implementation; may be {@code null}
970   *
971   * @see ContainerRequest
972   *
973   * @see SslContext
974   *
975   * @see
976   * HttpServerUpgradeHandler#HttpServerUpgradeHandler(SourceCodec,
977   * UpgradeCodecFactory, int)
978   *
979   * @see ApplicationHandler#handle(ContainerRequest)
980   *
981   * @see AbstractContainerRequestHandlingResponseWriter
982   *
983   * @see HttpObjectToContainerRequestDecoder
984   *
985   * @see HttpContainerRequestHandlingResponseWriter
986   *
987   * @see Http2StreamFrameToContainerRequestDecoder
988   *
989   * @see Http2ContainerRequestHandlingResponseWriter
990   */
991  public JerseyChannelInitializer(final URI baseUri,
992                                  final SslContext sslContext,
993                                  final boolean http2Support,
994                                  final long maxIncomingContentLength,
995                                  final EventExecutorGroup jerseyEventExecutorGroup,
996                                  final boolean useJerseyInjection,
997                                  Supplier<? extends ApplicationHandler> applicationHandlerSupplier,
998                                  final int flushThreshold,
999                                  final ByteBufCreator byteBufCreator) {
1000    super();
1001    this.baseUri = baseUri;
1002    this.sslContext = sslContext;
1003    this.http2Support = http2Support;
1004    // It's somewhat odd that Netty's MessageAggregator class (of
1005    // which HttpServerUpgradeHandler is a subclass) expresses a
1006    // maximum content length as an int, when Jersey and other
1007    // HTTP-centric frameworks express it as a long.  We will accept a
1008    // long and truncate it where necessary.
1009    if (maxIncomingContentLength < 0L) {
1010      this.maxIncomingContentLength = Long.MAX_VALUE;
1011    } else {
1012      this.maxIncomingContentLength = maxIncomingContentLength;
1013    }
1014    if (jerseyEventExecutorGroup == null) {
1015      this.jerseyEventExecutorGroup = new DefaultEventExecutorGroup(Runtime.getRuntime().availableProcessors()); // no idea how to size this
1016    } else {
1017      this.jerseyEventExecutorGroup = jerseyEventExecutorGroup;
1018    }
1019    if (applicationHandlerSupplier == null) {
1020      final ApplicationHandler applicationHandler = new ApplicationHandler();
1021      applicationHandlerSupplier = new ImmutableSupplier<>(applicationHandler);
1022    }
1023    if (useJerseyInjection) {
1024      // The idiom you see before you is apparently the right and only
1025      // way to install non-proxiable objects into request scope: you
1026      // install a factory that makes factories of mutable references
1027      // that produce the object you want, then elsewhere set the
1028      // payload of those references when you're actually in request
1029      // scope.  Really.  You'll find this pattern throughout the
1030      // Jersey codebase.  We follow suit here.
1031      final InjectionManager injectionManager = applicationHandlerSupplier.get().getInjectionManager();
1032      if (injectionManager != null) {
1033        injectionManager.register(Bindings.supplier(ChannelHandlerContextReferencingFactory.class)
1034                                    .to(ChannelHandlerContext.class)
1035                                    .proxy(false)
1036                                    .in(RequestScoped.class));
1037        injectionManager.register(Bindings.supplier(ReferencingFactory.<ChannelHandlerContext>referenceFactory())
1038                                    .to(ChannelHandlerContextReferencingFactory.genericRefType)
1039                                    .in(RequestScoped.class));
1040        injectionManager.register(Bindings.supplier(HttpRequestReferencingFactory.class)
1041                                    .to(HttpRequest.class)
1042                                    .proxy(false)
1043                                    .in(RequestScoped.class));
1044        injectionManager.register(Bindings.supplier(ReferencingFactory.<HttpRequest>referenceFactory())
1045                                    .to(HttpRequestReferencingFactory.genericRefType)
1046                                    .in(RequestScoped.class));
1047        if (http2Support) {
1048          injectionManager.register(Bindings.supplier(Http2HeadersFrameReferencingFactory.class)
1049                                      .to(Http2HeadersFrame.class)
1050                                      .proxy(false)
1051                                      .in(RequestScoped.class));
1052          injectionManager.register(Bindings.supplier(ReferencingFactory.<Http2HeadersFrame>referenceFactory())
1053                                      .to(Http2HeadersFrameReferencingFactory.genericRefType)
1054                                      .in(RequestScoped.class));
1055        }
1056      }
1057    }
1058    this.applicationHandlerSupplier = applicationHandlerSupplier;
1059    this.flushThreshold = Math.max(0, flushThreshold);
1060    this.byteBufCreator = byteBufCreator;
1061  }
1062
1063
1064  /*
1065   * Instance methods.
1066   */
1067
1068
1069  /**
1070   * Returns the {@link EventExecutorGroup} that this {@link
1071   * JerseyChannelInitializer} will use to offload blocking work from
1072   * the Netty event loop.
1073   *
1074   * <p>This method never returns {@code null}.</p>
1075   *
1076   * @return a non-{@code null} {@link EventExecutorGroup}
1077   *
1078   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
1079   * EventExecutorGroup, boolean, Supplier, int,
1080   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
1081   */
1082  public final EventExecutorGroup getJerseyEventExecutorGroup() {
1083    return this.jerseyEventExecutorGroup;
1084  }
1085
1086  /**
1087   * Returns the {@link URI} that was {@linkplain
1088   * #JerseyChannelInitializer(URI, SslContext, boolean, long,
1089   * EventExecutorGroup, boolean, Supplier, int,
1090   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
1091   * supplied at construction time}.
1092   *
1093   * <p>This method may return {@code null}.</p>
1094   *
1095   * @return the {@link URI} that was {@linkplain
1096   * #JerseyChannelInitializer(URI, SslContext, boolean, long,
1097   * EventExecutorGroup, boolean, Supplier, int,
1098   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
1099   * supplied at construction time}, or {@code null}
1100   *
1101   * @see #JerseyChannelInitializer(URI, SslContext, boolean, long,
1102   * EventExecutorGroup, boolean, Supplier, int,
1103   * AbstractByteBufBackedChannelOutboundInvokingOutputStream.ByteBufCreator)
1104   */
1105  public final URI getBaseUri() {
1106    return this.baseUri;
1107  }
1108
1109  /**
1110   * Initializes the supplied {@link Channel} using an appropriate
1111   * sequencing of several {@link ChannelHandler}s and other Netty
1112   * utility classes.
1113   *
1114   * <p>The {@link ChannelHandler}s and other classes involved include:</p>
1115   *
1116   * <ul>
1117   *
1118   * <li>{@link HttpObjectToContainerRequestDecoder}</li>
1119   *
1120   * <li>{@link HttpContainerRequestHandlingResponseWriter}</li>
1121   *
1122   * <li>{@link Http2StreamFrameToContainerRequestDecoder}</li>
1123   *
1124   * <li>{@link Http2ContainerRequestHandlingResponseWriter}</li>
1125   *
1126   * <li>{@link HttpServerCodec}</li>
1127   *
1128   * <li>{@link UpgradeCodecFactory}</li>
1129   *
1130   * <li>{@link UpgradeCodec}</li>
1131   *
1132   * <li>{@link Http2FrameCodecBuilder}</li>
1133   *
1134   * <li>{@link Http2FrameCodec}</li>
1135   *
1136   * <li>{@link Http2ServerUpgradeCodec}</li>
1137   *
1138   * <li>{@link Http2MultiplexHandler}</li>
1139   *
1140   * <li>{@link HttpServerUpgradeHandler}</li>
1141   *
1142   * <li>{@link CleartextHttp2ServerUpgradeHandler}</li>
1143   *
1144   * <li>{@link HttpServerExpectContinueHandler}</li>
1145   *
1146   * <li>{@link HttpNegotiationHandler}</li>
1147   *
1148   * </ul>
1149   *
1150   * <p>All of these classes collaborate to form a {@link
1151   * ChannelPipeline} that can handle HTTP 1.0, HTTP 1.1 and HTTP/2
1152   * scenarios, including upgrades.</p>
1153   *
1154   * @param channel the {@link Channel} to initialize; must not be
1155   * {@code null}
1156   *
1157   * @exception NullPointerException if {@code channel} is {@code
1158   * null}, or if the return value of {@link Channel#pipeline()
1159   * channel.pipeline()} is {@code null}
1160   */
1161  @Override
1162  protected final void initChannel(final Channel channel) {
1163    Objects.requireNonNull(channel);
1164    final ChannelPipeline channelPipeline = Objects.requireNonNull(channel.pipeline());
1165
1166    final SslHandler sslHandler;
1167    if (this.sslContext == null) {
1168      sslHandler = null;
1169    } else {
1170      sslHandler = createSslHandler(this.sslContext, channel.alloc());
1171    }
1172
1173    if (sslHandler == null) {
1174
1175      final HttpServerCodec httpServerCodec = new HttpServerCodec();
1176
1177      if (this.http2Support) {
1178
1179        // See https://github.com/netty/netty/issues/7079
1180        final int maxIncomingContentLength;
1181        if (this.maxIncomingContentLength >= Integer.MAX_VALUE) {
1182          maxIncomingContentLength = Integer.MAX_VALUE;
1183        } else {
1184          maxIncomingContentLength = (int)this.maxIncomingContentLength;
1185        }
1186
1187        final UpgradeCodecFactory upgradeCodecFactory = new UpgradeCodecFactory() {
1188            @Override
1189            public final UpgradeCodec newUpgradeCodec(final CharSequence protocolName) {
1190              final UpgradeCodec returnValue;
1191              if (protocolName == null ||
1192                  !AsciiString.contentEquals(Http2CodecUtil.HTTP_UPGRADE_PROTOCOL_NAME, protocolName)) {
1193                returnValue = null;
1194              } else {
1195                returnValue =
1196                  new Http2ServerUpgradeCodec(Http2FrameCodecBuilder.forServer().build(),
1197                                              new Http2MultiplexHandler(new Http2JerseyChannelInitializer(getJerseyEventExecutorGroup(),
1198                                                                                                          baseUri,
1199                                                                                                          applicationHandlerSupplier,
1200                                                                                                          flushThreshold,
1201                                                                                                          byteBufCreator)));
1202              }
1203              return returnValue;
1204            }
1205          };
1206
1207        // Create a handler that will deal with HTTP 1.1-to-HTTP/2
1208        // upgrade scenarios.  It by itself doesn't really do anything
1209        // but it will be supplied to a new instance of
1210        // CleartextHttp2ServerUpgradeHandler.
1211        final HttpServerUpgradeHandler httpServerUpgradeHandler =
1212          new HttpServerUpgradeHandler(httpServerCodec, upgradeCodecFactory, maxIncomingContentLength);
1213
1214        // Build a CleartextHttp2ServerUpgradeHandler.  This is really a
1215        // channel pipeline reconfigurator: it arranges things such
1216        // that:
1217        //
1218        //   * A private internal handler created inside the
1219        //     CleartextHttp2ServerUpgradeHandler class is added first
1220        //     (it will see if a prior knowledge situation is
1221        //     occurring and then will decide to do with the handlers
1222        //     supplied in this constructor; see
1223        //     https://github.com/netty/netty/blob/d8b1a2d93f556a08270e6549bf7f91b3b09f24bb/codec-http2/src/main/java/io/netty/handler/codec/http2/CleartextHttp2ServerUpgradeHandler.java#L74-L100
1224        //     for details)
1225        //
1226        //   * The first handler, an HttpServerCodec, MAY be added to
1227        //     the pipeline next (it will, if the prior knowledge
1228        //     handler doesn't bypass and remove it, be responsible
1229        //     for interpreting an HTTP 1.1 message that might be
1230        //     destined for an upgrade to HTTP/2)
1231        //
1232        //   * The second handler, an HttpServerUpgradeHandler,
1233        //     created by us above, will be added next if indeed the
1234        //     HttpServerCodec was actually added by the prior
1235        //     knowledge handler (it will read an HttpMessage (an HTTP
1236        //     1.1 message) and will see if it represents an upgrade
1237        //     request).  If this handler is actually added to the
1238        //     pipeline, then "prior knowledge" is not in effect.
1239        //
1240        //   * The third handler is held in reserve to be used only in
1241        //     those cases where prior knowledge is in effect; see
1242        //     https://github.com/netty/netty/blob/d8b1a2d93f556a08270e6549bf7f91b3b09f24bb/codec-http2/src/main/java/io/netty/handler/codec/http2/CleartextHttp2ServerUpgradeHandler.java#L90-L95
1243        //     for details and
1244        //     https://http2.github.io/http2-spec/#known-http for
1245        //     specification references.
1246        //
1247        // This API is tremendously confusing; it's not just you.
1248        final CleartextHttp2ServerUpgradeHandler cleartextHttp2ServerUpgradeHandler =
1249          new CleartextHttp2ServerUpgradeHandler(httpServerCodec,
1250                                                 httpServerUpgradeHandler,
1251                                                 new ChannelInitializer<Channel>() {
1252                                                   @Override
1253                                                   public final void initChannel(final Channel channel) {
1254                                                     // "Prior
1255                                                     // knowledge" is in
1256                                                     // effect.  See
1257                                                     // https://http2.github.io/http2-spec/#known-http.
1258                                                     final ChannelPipeline channelPipeline = channel.pipeline();
1259                                                     channelPipeline.addLast(Http2FrameCodec.class.getSimpleName(),
1260                                                                             Http2FrameCodecBuilder.forServer().build());
1261                                                     channelPipeline.addLast(Http2MultiplexHandler.class.getSimpleName(),
1262                                                                             new Http2MultiplexHandler(new Http2JerseyChannelInitializer(getJerseyEventExecutorGroup(),
1263                                                                                                                                         baseUri,
1264                                                                                                                                         applicationHandlerSupplier,
1265                                                                                                                                         flushThreshold,
1266                                                                                                                                         byteBufCreator)));
1267                                                   }
1268                                                 });
1269        channelPipeline.addLast(cleartextHttp2ServerUpgradeHandler);
1270
1271        // We add a CONDITIONAL handler for the (probably very common)
1272        // case where no one (a) connected with HTTP/2 or (b) asked
1273        // for an HTTP/2 upgrade.  In this case after all the
1274        // shenanigans we just jumped through we're just a regular old
1275        // common HTTP 1.1 connection.  Strangely, we have to handle
1276        // this in Netty as a special case even though it is likely to
1277        // be the most common one.
1278        channelPipeline.addLast(new SimpleChannelInboundHandler<HttpMessage>() {
1279            @Override
1280            protected final void channelRead0(final ChannelHandlerContext channelHandlerContext,
1281                                              final HttpMessage httpMessage)
1282              throws Exception {
1283              final ChannelPipeline channelPipeline = channelHandlerContext.pipeline();
1284
1285              // If we're actually called then we know that in "front"
1286              // of us is an HttpServerCodec because otherwise we
1287              // wouldn't have been called (note that our event is an
1288              // HttpMessage).  Now that we know this is going to be
1289              // HTTP 1.1 with no upgrades, replace *this* handler
1290              // we're "in" now with a handler that deals with HTTP
1291              // 100-class statuses...
1292              channelPipeline.replace(this,
1293                                      HttpServerExpectContinueHandler.class.getSimpleName(),
1294                                      new HttpServerExpectContinueHandler());
1295
1296              // ...and then after that add the "real" initializer (a
1297              // JerseyChannelSubInitializer instance, defined below
1298              // in this source file) that will install a
1299              // ChunkedWriteHandler followed by the main Jersey
1300              // integration.
1301              channelPipeline.addLast("HttpJerseyChannelInitializer",
1302                                      new HttpJerseyChannelInitializer(getJerseyEventExecutorGroup(),
1303                                                                       baseUri,
1304                                                                       applicationHandlerSupplier,
1305                                                                       flushThreshold,
1306                                                                       byteBufCreator));
1307
1308              // Forward the event on as we never touched it.
1309              channelHandlerContext.fireChannelRead(ReferenceCountUtil.retain(httpMessage));
1310            }
1311          });
1312      } else {
1313        channelPipeline.addLast(HttpServerCodec.class.getSimpleName(),
1314                                httpServerCodec);
1315        channelPipeline.addLast(HttpServerExpectContinueHandler.class.getSimpleName(),
1316                                new HttpServerExpectContinueHandler());
1317        channelPipeline.addLast("HttpJerseyChannelInitializer",
1318                                new HttpJerseyChannelInitializer(this.getJerseyEventExecutorGroup(),
1319                                                                 baseUri,
1320                                                                 applicationHandlerSupplier,
1321                                                                 flushThreshold,
1322                                                                 byteBufCreator));
1323      }
1324
1325
1326    } else {
1327
1328      // The SSL handler decodes TLS stuff...
1329      channelPipeline.addLast(sslHandler.getClass().getSimpleName(),
1330                              sslHandler);
1331
1332      // ...then the HttpNegotiationHandler does ALPN
1333      // (Application-Level Protocol Negotiation) to figure out
1334      // whether it's HTTP 1.1 or HTTP/2; see the private inner
1335      // class below for details.
1336      channelPipeline.addLast(HttpNegotiationHandler.class.getSimpleName(),
1337                              new HttpNegotiationHandler(this.getJerseyEventExecutorGroup(),
1338                                                         baseUri,
1339                                                         applicationHandlerSupplier,
1340                                                         flushThreshold,
1341                                                         byteBufCreator));
1342
1343    }
1344
1345  }
1346
1347  /**
1348   * Creates and returns a new {@link SslHandler} when invoked.
1349   *
1350   * <p>This method never returns {@code null}.</p>
1351   *
1352   * <p>Overrides of this method must not return {@code null}.</p>
1353   *
1354   * <p>This implementation calls {@link
1355   * SslContext#newHandler(ByteBufAllocator)
1356   * sslContext.newHandler(byteBufAllocator)} and returns the
1357   * result.</p>
1358   *
1359   * @param sslContext the {@link SslContext} that may assist in the
1360   * creation; must not be {@code null}
1361   *
1362   * @param byteBufAllocator a {@link ByteBufAllocator} that may
1363   * assist in the creation; must not be {@code null}
1364   *
1365   * @return a new {@link SslHandler}; never {@code null}
1366   *
1367   * @exception NullPointerException if {@code sslContext} is {@code null}
1368   *
1369   * @see SslContext#newHandler(ByteBufAllocator)
1370   */
1371  protected SslHandler createSslHandler(final SslContext sslContext, final ByteBufAllocator byteBufAllocator) {
1372    return sslContext.newHandler(byteBufAllocator);
1373  }
1374
1375
1376  /*
1377   * Static methods.
1378   */
1379
1380
1381  private static final Supplier<? extends ApplicationHandler> toApplicationHandlerSupplier(final Application application) {
1382    return toApplicationHandlerSupplier(application == null ? new ApplicationHandler() : new ApplicationHandler(application));
1383  }
1384
1385  private static final Supplier<? extends ApplicationHandler> toApplicationHandlerSupplier(final ApplicationHandler suppliedApplicationHandler) {
1386    return new ImmutableSupplier<>(suppliedApplicationHandler == null ? new ApplicationHandler() : suppliedApplicationHandler);
1387  }
1388
1389  private static final Supplier<? extends Configuration> toConfigurationSupplier(final Supplier<? extends ApplicationHandler> applicationHandlerSupplier) {
1390    return applicationHandlerSupplier == null ? JerseyChannelInitializer::returnNullConfiguration : new ConfigurationSupplier(applicationHandlerSupplier);
1391  }
1392
1393  private static final Configuration returnNullConfiguration() {
1394    return null;
1395  }
1396
1397  private static final ApplicationHandler returnNullApplicationHandler() {
1398    return null;
1399  }
1400
1401
1402  /*
1403   * Inner and nested classes.
1404   */
1405
1406
1407  private static final class ConfigurationSupplier implements Supplier<Configuration> {
1408
1409    private final Supplier<? extends ApplicationHandler> applicationHandlerSupplier;
1410
1411    private ConfigurationSupplier(final Supplier<? extends ApplicationHandler> applicationHandlerSupplier) {
1412      super();
1413      this.applicationHandlerSupplier = applicationHandlerSupplier == null ? JerseyChannelInitializer::returnNullApplicationHandler : applicationHandlerSupplier;
1414    }
1415
1416    @Override
1417    public final Configuration get() {
1418      final ApplicationHandler applicationHandler = this.applicationHandlerSupplier.get();
1419      return applicationHandler == null ? null : applicationHandler.getConfiguration();
1420    }
1421
1422  }
1423
1424  /**
1425   * A {@link ChannelInitializer} that {@linkplain
1426   * ChannelPipeline#addLast(String, ChannelHandler) adds} an {@link
1427   * HttpObjectToContainerRequestDecoder} followed by an {@link
1428   * HttpContainerRequestHandlingResponseWriter} (which is added with
1429   * its own {@link EventExecutorGroup}).
1430   *
1431   * @author <a href="https://about.me/lairdnelson"
1432   * target="_parent">Laird Nelson</a>
1433   *
1434   * @see ChannelInitializer
1435   */
1436  private static final class HttpJerseyChannelInitializer extends ChannelInitializer<Channel> {
1437
1438    private final EventExecutorGroup jerseyEventExecutorGroup;
1439
1440    private final URI baseUri;
1441
1442    private final Supplier<? extends ApplicationHandler> applicationHandlerSupplier;
1443
1444    private final Supplier<? extends Configuration> configurationSupplier;
1445
1446    private final int flushThreshold;
1447
1448    private final ByteBufCreator byteBufCreator;
1449
1450    /**
1451     * Creates a new {@link HttpJerseyChannelInitializer}.
1452     */
1453    private HttpJerseyChannelInitializer(final EventExecutorGroup jerseyEventExecutorGroup,
1454                                         final URI baseUri,
1455                                         final Supplier<? extends ApplicationHandler> applicationHandlerSupplier,
1456                                         final int flushThreshold,
1457                                         final ByteBufCreator byteBufCreator) {
1458      super();
1459      this.jerseyEventExecutorGroup = Objects.requireNonNull(jerseyEventExecutorGroup);
1460      this.baseUri = baseUri;
1461      this.applicationHandlerSupplier = applicationHandlerSupplier;
1462      this.configurationSupplier = toConfigurationSupplier(applicationHandlerSupplier);
1463      this.flushThreshold = Math.max(0, flushThreshold);
1464      this.byteBufCreator = byteBufCreator;
1465    }
1466
1467    /**
1468     * {@linkplain ChannelPipeline#addLast(String, ChannelHandler)
1469     * Adds} an {@link
1470     * HttpObjectToContainerRequestDecoder} followed by an {@link
1471     * HttpContainerRequestHandlingResponseWriter} (which is added with
1472     * its own {@link EventExecutorGroup})
1473     *
1474     * @param channel the {@link Channel} being configured; must
1475     * not be {@code null}
1476     *
1477     */
1478    @Override
1479    protected final void initChannel(final Channel channel) {
1480      final ChannelPipeline channelPipeline = channel.pipeline();
1481      channelPipeline.addLast(HttpObjectToContainerRequestDecoder.class.getSimpleName(),
1482                              new HttpObjectToContainerRequestDecoder(baseUri, this.configurationSupplier));
1483      channelPipeline.addLast(jerseyEventExecutorGroup,
1484                              HttpContainerRequestHandlingResponseWriter.class.getSimpleName(),
1485                              new HttpContainerRequestHandlingResponseWriter(applicationHandlerSupplier,
1486                                                                             flushThreshold,
1487                                                                             byteBufCreator));
1488    }
1489
1490  }
1491
1492
1493  /**
1494   * A {@link ChannelInitializer} that {@linkplain
1495   * ChannelPipeline#addLast(String, ChannelHandler) adds} an {@link
1496   * Http2StreamFrameToContainerRequestDecoder} followed by an {@link
1497   * Http2ContainerRequestHandlingResponseWriter} (which is added with
1498   * its own {@link EventExecutorGroup}).
1499   *
1500   * @author <a href="https://about.me/lairdnelson"
1501   * target="_parent">Laird Nelson</a>
1502   *
1503   * @see ChannelInitializer
1504   */
1505  private static final class Http2JerseyChannelInitializer extends ChannelInitializer<Channel> {
1506
1507    private final EventExecutorGroup jerseyEventExecutorGroup;
1508
1509    private final URI baseUri;
1510
1511    private final Supplier<? extends ApplicationHandler> applicationHandlerSupplier;
1512
1513    private final Supplier<? extends Configuration> configurationSupplier;
1514
1515    private final int flushThreshold;
1516
1517    private final ByteBufCreator byteBufCreator;
1518
1519    /**
1520     * Creates a new {@link Http2JerseyChannelInitializer}.
1521     */
1522    private Http2JerseyChannelInitializer(final EventExecutorGroup jerseyEventExecutorGroup,
1523                                          final URI baseUri,
1524                                          final Supplier<? extends ApplicationHandler> applicationHandlerSupplier,
1525                                          final int flushThreshold,
1526                                          final ByteBufCreator byteBufCreator) {
1527      super();
1528      this.jerseyEventExecutorGroup = Objects.requireNonNull(jerseyEventExecutorGroup);
1529      this.baseUri = baseUri;
1530      this.applicationHandlerSupplier = applicationHandlerSupplier;
1531      this.configurationSupplier = toConfigurationSupplier(applicationHandlerSupplier);
1532      this.flushThreshold = Math.max(0, flushThreshold);
1533      this.byteBufCreator = byteBufCreator;
1534    }
1535
1536    /**
1537     * {@linkplain ChannelPipeline#addLast(String, ChannelHandler)
1538     * Adds} an {@link
1539     * Http2StreamFrameToContainerRequestDecoder} followed by an {@link
1540     * Http2ContainerRequestHandlingResponseWriter} (which is added with
1541     * its own {@link EventExecutorGroup}).
1542     *
1543     * @param channel the {@link Channel} being configured; must
1544     * not be {@code null}
1545     *
1546     * @exception NullPointerException if {@code channel} is {@code
1547     * null}
1548     */
1549    @Override
1550    protected final void initChannel(final Channel channel) {
1551      final ChannelPipeline channelPipeline = channel.pipeline();
1552      channelPipeline.addLast(Http2StreamFrameToContainerRequestDecoder.class.getSimpleName(),
1553                              new Http2StreamFrameToContainerRequestDecoder(baseUri, this.configurationSupplier));
1554      channelPipeline.addLast(jerseyEventExecutorGroup,
1555                              Http2ContainerRequestHandlingResponseWriter.class.getSimpleName(),
1556                              new Http2ContainerRequestHandlingResponseWriter(this.applicationHandlerSupplier));
1557    }
1558
1559  }
1560
1561  /**
1562   * An {@link ApplicationProtocolNegotiationHandler} that knows how
1563   * to configure a {@link ChannelPipeline} for HTTP 1.1 or HTTP/2
1564   * requests that require Jersey integration.
1565   *
1566   * @author <a href="https://about.me/lairdnelson"
1567   * target="_parent">Laird Nelson</a>
1568   *
1569   * @see ApplicationProtocolNegotiationHandler
1570   */
1571  private static final class HttpNegotiationHandler extends ApplicationProtocolNegotiationHandler {
1572
1573    private final EventExecutorGroup jerseyEventExecutorGroup;
1574
1575    private final URI baseUri;
1576
1577    private final Supplier<? extends ApplicationHandler> applicationHandlerSupplier;
1578
1579    private final int flushThreshold;
1580
1581    private final ByteBufCreator byteBufCreator;
1582    /**
1583     * Creates a new {@link HttpNegotiationHandler}.
1584     */
1585    private HttpNegotiationHandler(final EventExecutorGroup jerseyEventExecutorGroup,
1586                                   final URI baseUri,
1587                                   final Supplier<? extends ApplicationHandler> applicationHandlerSupplier,
1588                                   final int flushThreshold,
1589                                   final ByteBufCreator byteBufCreator) {
1590      super(ApplicationProtocolNames.HTTP_1_1);
1591      this.jerseyEventExecutorGroup = Objects.requireNonNull(jerseyEventExecutorGroup);
1592      this.baseUri = baseUri;
1593      this.applicationHandlerSupplier = applicationHandlerSupplier;
1594      this.flushThreshold = Math.max(0, flushThreshold);
1595      this.byteBufCreator = byteBufCreator;
1596    }
1597
1598    /**
1599     * Sets up the {@linkplain ChannelHandlerContext#pipeline()
1600     * current pipeline} for HTTP 1.1 or HTTP/2 requests that require
1601     * Jersey integration.
1602     *
1603     * @param channelHandlerContext a {@link ChannelHandlerContext}
1604     * representing the current Netty execution; must not be {@code
1605     * null}
1606     *
1607     * @param protocol the protocol that was negotiated; must be equal
1608     * to either {@link ApplicationProtocolNames#HTTP_2} or {@link
1609     * ApplicationProtocolNames#HTTP_1_1}
1610     *
1611     * @exception NullPointerException if {@code
1612     * channelHandlerContext} or {@code protocol} is {@code null}
1613     *
1614     * @exception IllegalArgumentException if {@code protocol} is not
1615     * equal to the value of either the {@link
1616     * ApplicationProtocolNames#HTTP_1_1} or {@link
1617     * ApplicationProtocolNames#HTTP_2} constants
1618     */
1619    @Override
1620    protected final void configurePipeline(final ChannelHandlerContext channelHandlerContext, final String protocol) {
1621      final ChannelPipeline channelPipeline = channelHandlerContext.pipeline();
1622      switch (protocol) {
1623      case ApplicationProtocolNames.HTTP_2:
1624        channelPipeline.addLast(Http2FrameCodec.class.getSimpleName(),
1625                                Http2FrameCodecBuilder.forServer().build());
1626        channelPipeline.addLast(Http2MultiplexHandler.class.getSimpleName(),
1627                                new Http2MultiplexHandler(new Http2JerseyChannelInitializer(jerseyEventExecutorGroup,
1628                                                                                            baseUri,
1629                                                                                            applicationHandlerSupplier,
1630                                                                                            flushThreshold,
1631                                                                                            byteBufCreator)));
1632        break;
1633      case ApplicationProtocolNames.HTTP_1_1:
1634        channelPipeline.addLast(HttpServerCodec.class.getSimpleName(),
1635                                new HttpServerCodec());
1636        channelPipeline.addLast(HttpServerExpectContinueHandler.class.getSimpleName(),
1637                                new HttpServerExpectContinueHandler());
1638        channelPipeline.addLast("HttpJerseyChannelInitializer",
1639                                new HttpJerseyChannelInitializer(jerseyEventExecutorGroup,
1640                                                                 baseUri,
1641                                                                 applicationHandlerSupplier,
1642                                                                 flushThreshold,
1643                                                                 byteBufCreator));
1644        break;
1645      default:
1646        throw new IllegalArgumentException("protocol: " + protocol);
1647      }
1648    }
1649
1650  }
1651
1652}