master d1485e7d4c8f cached
48 files
142.5 KB
33.3k tokens
366 symbols
1 requests
Download .txt
Repository: DanielThomas/spring-boot-starter-netty
Branch: master
Commit: d1485e7d4c8f
Files: 48
Total size: 142.5 KB

Directory structure:
gitextract_f34d6oz9/

├── .gitignore
├── .travis.yml
├── LICENSE.txt
├── NOTICE.txt
├── README.md
├── build.gradle
├── gradle/
│   ├── benchmark.gradle
│   ├── dependencies.gradle
│   ├── idea-codestyle.xml
│   ├── idea-copyright.xml
│   ├── idea-entrypoints.xml
│   ├── idea-inspections.xml
│   ├── idea.gradle
│   ├── integTest.gradle
│   ├── maven.gradle
│   ├── test.gradle
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src/
    ├── integTest/
    │   ├── groovy/
    │   │   └── org/
    │   │       └── springframework/
    │   │           └── boot/
    │   │               └── context/
    │   │                   └── embedded/
    │   │                       └── netty/
    │   │                           └── NettyEmbeddedServletContainerAutoConfigurationIntegrationTest.groovy
    │   ├── java/
    │   │   └── org/
    │   │       └── springframework/
    │   │           └── boot/
    │   │               └── context/
    │   │                   └── embedded/
    │   │                       └── netty/
    │   │                           ├── HttpContentInputStreamBenchmark.java
    │   │                           ├── HttpResponseOutputStreamBenchmark.java
    │   │                           ├── NettyHttpServletResponseBenchmark.java
    │   │                           ├── StubChannelHandlerContext.java
    │   │                           └── TestApplication.java
    │   └── resources/
    │       └── logback.xml
    ├── main/
    │   └── java/
    │       └── org/
    │           └── springframework/
    │               └── boot/
    │                   └── context/
    │                       └── embedded/
    │                           └── netty/
    │                               ├── AbstractNettyRegistration.java
    │                               ├── HttpContentInputStream.java
    │                               ├── HttpResponseOutputStream.java
    │                               ├── NettyAsyncContext.java
    │                               ├── NettyEmbeddedContext.java
    │                               ├── NettyEmbeddedServletContainer.java
    │                               ├── NettyEmbeddedServletContainerAutoConfiguration.java
    │                               ├── NettyEmbeddedServletContainerFactory.java
    │                               ├── NettyEmbeddedServletInitializer.java
    │                               ├── NettyFilterRegistration.java
    │                               ├── NettyHttpServletRequest.java
    │                               ├── NettyHttpServletResponse.java
    │                               ├── NettyRequestDispatcher.java
    │                               ├── NettyServletRegistration.java
    │                               ├── RequestDispatcherHandler.java
    │                               ├── ServletContentHandler.java
    │                               ├── SimpleFilterChain.java
    │                               └── package-info.java
    └── test/
        └── groovy/
            └── org/
                └── springframework/
                    └── boot/
                        └── context/
                            └── embedded/
                                └── netty/
                                    ├── HttpContentInputStreamTest.groovy
                                    └── PackageSanityTest.groovy

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
### Gradle ###
.gradle
build/

### Intellij ###

## Directory-based project format
.idea/

## File-based project format
*.ipr
*.iml
*.iws

## Additional for IntelliJ
out/


================================================
FILE: .travis.yml
================================================
language: java


================================================
FILE: LICENSE.txt
================================================

                                 Apache License
                           Version 2.0, January 2004
                        http://www.apache.org/licenses/

   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

   1. Definitions.

      "License" shall mean the terms and conditions for use, reproduction,
      and distribution as defined by Sections 1 through 9 of this document.

      "Licensor" shall mean the copyright owner or entity authorized by
      the copyright owner that is granting the License.

      "Legal Entity" shall mean the union of the acting entity and all
      other entities that control, are controlled by, or are under common
      control with that entity. For the purposes of this definition,
      "control" means (i) the power, direct or indirect, to cause the
      direction or management of such entity, whether by contract or
      otherwise, or (ii) ownership of fifty percent (50%) or more of the
      outstanding shares, or (iii) beneficial ownership of such entity.

      "You" (or "Your") shall mean an individual or Legal Entity
      exercising permissions granted by this License.

      "Source" form shall mean the preferred form for making modifications,
      including but not limited to software source code, documentation
      source, and configuration files.

      "Object" form shall mean any form resulting from mechanical
      transformation or translation of a Source form, including but
      not limited to compiled object code, generated documentation,
      and conversions to other media types.

      "Work" shall mean the work of authorship, whether in Source or
      Object form, made available under the License, as indicated by a
      copyright notice that is included in or attached to the work
      (an example is provided in the Appendix below).

      "Derivative Works" shall mean any work, whether in Source or Object
      form, that is based on (or derived from) the Work and for which the
      editorial revisions, annotations, elaborations, or other modifications
      represent, as a whole, an original work of authorship. For the purposes
      of this License, Derivative Works shall not include works that remain
      separable from, or merely link (or bind by name) to the interfaces of,
      the Work and Derivative Works thereof.

      "Contribution" shall mean any work of authorship, including
      the original version of the Work and any modifications or additions
      to that Work or Derivative Works thereof, that is intentionally
      submitted to Licensor for inclusion in the Work by the copyright owner
      or by an individual or Legal Entity authorized to submit on behalf of
      the copyright owner. For the purposes of this definition, "submitted"
      means any form of electronic, verbal, or written communication sent
      to the Licensor or its representatives, including but not limited to
      communication on electronic mailing lists, source code control systems,
      and issue tracking systems that are managed by, or on behalf of, the
      Licensor for the purpose of discussing and improving the Work, but
      excluding communication that is conspicuously marked or otherwise
      designated in writing by the copyright owner as "Not a Contribution."

      "Contributor" shall mean Licensor and any individual or Legal Entity
      on behalf of whom a Contribution has been received by Licensor and
      subsequently incorporated within the Work.

   2. Grant of Copyright License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      copyright license to reproduce, prepare Derivative Works of,
      publicly display, publicly perform, sublicense, and distribute the
      Work and such Derivative Works in Source or Object form.

   3. Grant of Patent License. Subject to the terms and conditions of
      this License, each Contributor hereby grants to You a perpetual,
      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
      (except as stated in this section) patent license to make, have made,
      use, offer to sell, sell, import, and otherwise transfer the Work,
      where such license applies only to those patent claims licensable
      by such Contributor that are necessarily infringed by their
      Contribution(s) alone or by combination of their Contribution(s)
      with the Work to which such Contribution(s) was submitted. If You
      institute patent litigation against any entity (including a
      cross-claim or counterclaim in a lawsuit) alleging that the Work
      or a Contribution incorporated within the Work constitutes direct
      or contributory patent infringement, then any patent licenses
      granted to You under this License for that Work shall terminate
      as of the date such litigation is filed.

   4. Redistribution. You may reproduce and distribute copies of the
      Work or Derivative Works thereof in any medium, with or without
      modifications, and in Source or Object form, provided that You
      meet the following conditions:

      (a) You must give any other recipients of the Work or
          Derivative Works a copy of this License; and

      (b) You must cause any modified files to carry prominent notices
          stating that You changed the files; and

      (c) You must retain, in the Source form of any Derivative Works
          that You distribute, all copyright, patent, trademark, and
          attribution notices from the Source form of the Work,
          excluding those notices that do not pertain to any part of
          the Derivative Works; and

      (d) If the Work includes a "NOTICE" text file as part of its
          distribution, then any Derivative Works that You distribute must
          include a readable copy of the attribution notices contained
          within such NOTICE file, excluding those notices that do not
          pertain to any part of the Derivative Works, in at least one
          of the following places: within a NOTICE text file distributed
          as part of the Derivative Works; within the Source form or
          documentation, if provided along with the Derivative Works; or,
          within a display generated by the Derivative Works, if and
          wherever such third-party notices normally appear. The contents
          of the NOTICE file are for informational purposes only and
          do not modify the License. You may add Your own attribution
          notices within Derivative Works that You distribute, alongside
          or as an addendum to the NOTICE text from the Work, provided
          that such additional attribution notices cannot be construed
          as modifying the License.

      You may add Your own copyright statement to Your modifications and
      may provide additional or different license terms and conditions
      for use, reproduction, or distribution of Your modifications, or
      for any such Derivative Works as a whole, provided Your use,
      reproduction, and distribution of the Work otherwise complies with
      the conditions stated in this License.

   5. Submission of Contributions. Unless You explicitly state otherwise,
      any Contribution intentionally submitted for inclusion in the Work
      by You to the Licensor shall be under the terms and conditions of
      this License, without any additional terms or conditions.
      Notwithstanding the above, nothing herein shall supersede or modify
      the terms of any separate license agreement you may have executed
      with Licensor regarding such Contributions.

   6. Trademarks. This License does not grant permission to use the trade
      names, trademarks, service marks, or product names of the Licensor,
      except as required for reasonable and customary use in describing the
      origin of the Work and reproducing the content of the NOTICE file.

   7. Disclaimer of Warranty. Unless required by applicable law or
      agreed to in writing, Licensor provides the Work (and each
      Contributor provides its Contributions) on an "AS IS" BASIS,
      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
      implied, including, without limitation, any warranties or conditions
      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
      PARTICULAR PURPOSE. You are solely responsible for determining the
      appropriateness of using or redistributing the Work and assume any
      risks associated with Your exercise of permissions under this License.

   8. Limitation of Liability. In no event and under no legal theory,
      whether in tort (including negligence), contract, or otherwise,
      unless required by applicable law (such as deliberate and grossly
      negligent acts) or agreed to in writing, shall any Contributor be
      liable to You for damages, including any direct, indirect, special,
      incidental, or consequential damages of any character arising as a
      result of this License or out of the use or inability to use the
      Work (including but not limited to damages for loss of goodwill,
      work stoppage, computer failure or malfunction, or any and all
      other commercial damages or losses), even if such Contributor
      has been advised of the possibility of such damages.

   9. Accepting Warranty or Additional Liability. While redistributing
      the Work or Derivative Works thereof, You may choose to offer,
      and charge a fee for, acceptance of support, warranty, indemnity,
      or other liability obligations and/or rights consistent with this
      License. However, in accepting such obligations, You may act only
      on Your own behalf and on Your sole responsibility, not on behalf
      of any other Contributor, and only if You agree to indemnify,
      defend, and hold each Contributor harmless for any liability
      incurred by, or claims asserted against, such Contributor by reason
      of your accepting any such warranty or additional liability.

   END OF TERMS AND CONDITIONS

   APPENDIX: How to apply the Apache License to your work.

      To apply the Apache License to your work, attach the following
      boilerplate notice, with the fields enclosed by brackets "[]"
      replaced with your own identifying information. (Don't include
      the brackets!)  The text should be enclosed in the appropriate
      comment syntax for the file format. We also recommend that a
      file or class name and description of purpose be included on the
      same "printed page" as the copyright notice for easier
      identification within third-party archives.

   Copyright [yyyy] [name of copyright owner]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.


================================================
FILE: NOTICE.txt
================================================


================================================
FILE: README.md
================================================
A prototype Netty embedded servlet bridge for Spring Boot.

Includes basic filter and servlet support. I'm fairly new to Spring Boot, but this approach seems to fit it's opinionated view of the servlet container. Async servlet support isn't yet completed.

[![Build Status](https://travis-ci.org/DanielThomas/spring-boot-starter-netty.svg?branch=master)](https://travis-ci.org/DanielThomas/spring-boot-starter-netty)

Performance
=============

Use the `runTestApp` Gradle task to start the server with the same configuration used here. Tests run with `wrk` with the following arguments:

    wrk -H 'Host: localhost' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' -H 'Connection: keep-alive' -d 120 -c 32 -t 2 http://localhost:8080/plaintext

Tomcat 7.0.55
-------------

    Running 2m test @ http://localhost:8080/plaintext
      2 threads and 32 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency    22.96ms  115.34ms 628.47ms   96.50%
        Req/Sec    16.33k     4.74k   34.44k    83.57%
      3691775 requests in 2.00m, 497.09MB read
    Requests/sec:  30764.62
    Transfer/sec:      4.14MB

Tomcat 8.0.9
-------------

    Running 2m test @ http://localhost:8080/plaintext
      2 threads and 32 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency   114.10ms  745.91ms   5.04s    97.75%
        Req/Sec    15.67k     2.99k   27.56k    91.68%
      3553322 requests in 2.00m, 478.45MB read
      Socket errors: connect 0, read 0, write 0, timeout 3
    Requests/sec:  29611.00
    Transfer/sec:      3.99MB

Prototype Netty 4.0 Bridge
-------------

    Running 2m test @ http://localhost:8080/plaintext
      2 threads and 32 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     1.14ms    6.64ms 128.33ms   99.33%
        Req/Sec    19.64k     4.16k   45.22k    83.96%
      4459068 requests in 2.00m, 331.69MB read
    Requests/sec:  37158.91
    Transfer/sec:      2.76MB

Note: Difference in transfer/sec is due to Server and Date headers returned by Tomcat

Prototype Netty 4.1 Beta 1 Bridge
-------------

    Running 2m test @ http://localhost:8080/plaintext
      2 threads and 32 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     1.09ms    7.58ms 200.99ms   99.80%
        Req/Sec    19.14k     2.19k   39.89k    84.44%
      4366902 requests in 2.00m, 408.12MB read
    Requests/sec:  36390.84
    Transfer/sec:      3.40MB

When compared to a null servlet:

    Running 2m test @ http://localhost:8080/null
      2 threads and 32 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency   820.84us    3.47ms  66.04ms   99.70%
        Req/Sec    26.03k     4.27k   45.44k    69.68%
      5894335 requests in 2.00m, 505.91MB read
    Requests/sec:  49119.58

And to serving the response directly from Netty:

    Running 2m test @ http://localhost:8080/nullnetty
      2 threads and 32 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     2.01ms   23.54ms 400.01ms   99.65%
        Req/Sec    27.21k     4.26k   41.44k    66.08%
      6164886 requests in 2.00m, 223.41MB read
    Requests/sec:  51374.16

Prototype Netty 4.1 Beta 3 Bridge (Commit eb531c6)
-------------

    Running 2m test @ http://localhost:8080/plaintext
      2 threads and 32 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     1.95ms   18.62ms 289.53ms   99.57%
        Req/Sec    20.48k     2.55k   37.78k    86.51%
      4637061 requests in 2.00m, 698.71MB read
    Requests/sec:  38642.24
    Transfer/sec:      5.82MB


================================================
FILE: build.gradle
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

plugins {
    id 'java'
    id 'groovy'
    id 'com.github.ben-manes.versions' version '0.11.3'
}

version '1.0-SNAPSHOT'
description 'Spring Boot Netty Starter'

apply from: 'gradle/dependencies.gradle'
apply from: 'gradle/idea.gradle'
apply from: 'gradle/maven.gradle'
apply from: 'gradle/test.gradle'

dependencies {
    compile libraries.guava
    compile libraries.netty
    compile libraries.servletapi
    compile libraries.springboot

    testCompile libraries.testlibs
}

jar {
    manifest {
        attributes('Implementation-Title': description, 'Implementation-Version': version)
    }
}

task wrapper(type: Wrapper) { gradleVersion = '2.8' }

repositories {
    jcenter()
}


================================================
FILE: gradle/benchmark.gradle
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

dependencies {
    testCompile 'org.openjdk.jmh:jmh-generator-annprocess:1.11.2'
}

task(benchmark, type: JavaExec) {
    classpath sourceSets.test.runtimeClasspath
    main = 'org.openjdk.jmh.Main'
}

task(integBenchmark, type: JavaExec) {
    classpath sourceSets.integTest.runtimeClasspath
    main = 'org.openjdk.jmh.Main'
}


================================================
FILE: gradle/dependencies.gradle
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

ext {
    libraries = [:]
    versions = [:]
}

versions.guava = '18.0'
versions.spock = '1.0-groovy-2.4'
versions.springboot = '1.2.7.RELEASE'

configurations.all {
    resolutionStrategy {
        eachDependency { details ->
            switch (details.requested.name) {
                case 'junit':
                case 'junit-dep':
                    details.useTarget 'junit:junit:4.11'
                    break
            }
            if (details.requested.group == 'org.apache.tomcat.embed') {
                details.useVersion '8.0.9'
            }
        }
        def isCiServer = System.getenv().containsKey('HUDSON_HOME')
        if (isCiServer) {
            cacheChangingModulesFor 0, 'seconds'
        }
    }
}


libraries.guava = [
        "com.google.guava:guava:$versions.guava",
        'com.google.code.findbugs:jsr305:3.0.1'
]
libraries.netty = [
        'io.netty:netty-all:4.1.0.Beta7',
        'org.javassist:javassist:3.20.0-GA',
        'com.jcraft:jzlib:1.1.3',
        'javax.el:javax.el-api:2.2.5'
]
libraries.servletapi = 'javax.servlet:javax.servlet-api:3.1.0'

libraries.springboot = [
        dependencies.create("org.springframework.boot:spring-boot-starter-web:$versions.springboot") {
            exclude module: 'spring-boot-starter-tomcat'
        }
]

libraries.guavatest = "com.google.guava:guava-testlib:$versions.guava"
libraries.spock = [
        "org.spockframework:spock-core:$versions.spock",
        'cglib:cglib-nodep:3.2.0',
        'org.objenesis:objenesis:2.2'
]

libraries.testlibs = [
        libraries.guavatest,
        libraries.spock
]


================================================
FILE: gradle/idea-codestyle.xml
================================================
<!--
  ~ Copyright 2014 the original author or authors.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~   http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  ~
  -->

<component name="ProjectCodeStyleSettingsManager">
  <option name="PER_PROJECT_SETTINGS">
    <value>
      <option name="IMPORT_LAYOUT_TABLE">
        <value>
          <package name="io.groundhog" withSubpackages="true" static="false"/>
          <emptyLine/>
          <package name="" withSubpackages="true" static="false"/>
          <emptyLine/>
          <package name="javax" withSubpackages="true" static="false"/>
          <package name="java" withSubpackages="true" static="false"/>
          <emptyLine/>
          <package name="" withSubpackages="true" static="true"/>
        </value>
      </option>
      <codeStyleSettings language="Groovy">
        <indentOptions>
          <option name="INDENT_SIZE" value="4"/>
          <option name="CONTINUATION_INDENT_SIZE" value="8"/>
          <option name="TAB_SIZE" value="4"/>
        </indentOptions>
      </codeStyleSettings>
      <codeStyleSettings language="JAVA">
        <indentOptions>
          <option name="INDENT_SIZE" value="4"/>
          <option name="CONTINUATION_INDENT_SIZE" value="8"/>
          <option name="TAB_SIZE" value="4"/>
        </indentOptions>
        <arrangement>
          <groups>
            <group>
              <type>GETTERS_AND_SETTERS</type>
              <order>KEEP</order>
            </group>
          </groups>
          <rules>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <FINAL/>
                  <PUBLIC/>
                  <STATIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <FINAL/>
                  <PROTECTED/>
                  <STATIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <FINAL/>
                  <PACKAGE_PRIVATE/>
                  <STATIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <FINAL/>
                  <PRIVATE/>
                  <STATIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <PUBLIC/>
                  <STATIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <PROTECTED/>
                  <STATIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <PACKAGE_PRIVATE/>
                  <STATIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <PRIVATE/>
                  <STATIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <FINAL/>
                  <PUBLIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <FINAL/>
                  <PROTECTED/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <FINAL/>
                  <PACKAGE_PRIVATE/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <FINAL/>
                  <PRIVATE/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <PUBLIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <PROTECTED/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <PACKAGE_PRIVATE/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <FIELD/>
                  <PRIVATE/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <FIELD/>
              </match>
            </rule>
            <rule>
              <match>
                <CONSTRUCTOR/>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <METHOD/>
                  <STATIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <METHOD/>
              </match>
            </rule>
            <rule>
              <match>
                <ENUM/>
              </match>
            </rule>
            <rule>
              <match>
                <INTERFACE/>
              </match>
            </rule>
            <rule>
              <match>
                <AND>
                  <CLASS/>
                  <STATIC/>
                </AND>
              </match>
            </rule>
            <rule>
              <match>
                <CLASS/>
              </match>
            </rule>
          </rules>
        </arrangement>
      </codeStyleSettings>
      <XML>
        <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true"/>
      </XML>
      <codeStyleSettings language="XML">
        <indentOptions>
          <option name="INDENT_SIZE" value="2"/>
          <option name="CONTINUATION_INDENT_SIZE" value="4"/>
          <option name="TAB_SIZE" value="2"/>
        </indentOptions>
        <arrangement>
          <rules>
            <rule>
              <match>
                <NAME>xmlns:.*</NAME>
              </match>
            </rule>
          </rules>
        </arrangement>
      </codeStyleSettings>
    </value>
  </option>
  <option name="USE_PER_PROJECT_SETTINGS" value="true"/>
</component>


================================================
FILE: gradle/idea-copyright.xml
================================================
<!--
  ~ Copyright 2014 the original author or authors.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~   http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  ~
  -->

<component name="CopyrightManager" default="Apache 2">
  <copyright>
    <option name="notice"
            value="Copyright $today.year the original author or authors.&#10;&#10;Licensed under the Apache License, Version 2.0 (the &quot;License&quot;);&#10;you may not use this file except in compliance with the License.&#10;You may obtain a copy of the License at&#10;&#10;&#32;&#32;http://www.apache.org/licenses/LICENSE-2.0&#10;&#10;Unless required by applicable law or agreed to in writing, software&#10;distributed under the License is distributed on an &quot;AS IS&quot; BASIS,&#10;WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.&#10;See the License for the specific language governing permissions and&#10;limitations under the License.&#10;"/>
    <option name="keyword" value="Copyright"/>
    <option name="allowReplaceKeyword" value=""/>
    <option name="myName" value="Apache 2"/>
    <option name="myLocal" value="true"/>
  </copyright>
  <module2copyright>
    <element module="Project Files" copyright="Apache 2"/>
  </module2copyright>
</component>


================================================
FILE: gradle/idea-entrypoints.xml
================================================
<component name="EntryPointsManager">
  <entry_points version="2.0"/>
  <list size="4">
    <item index="0" class="java.lang.String" itemvalue="org.openjdk.jmh.annotations.Benchmark"/>
    <item index="1" class="java.lang.String" itemvalue="org.openjdk.jmh.annotations.Setup"/>
    <item index="2" class="java.lang.String" itemvalue="org.openjdk.jmh.annotations.TearDown"/>
    <item index="3" class="java.lang.String" itemvalue="org.springframework.web.bind.annotation.RequestMapping"/>
  </list>
</component>


================================================
FILE: gradle/idea-inspections.xml
================================================
<!--
  ~ Copyright 2014 the original author or authors.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~   http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  ~
  -->

<component name="InspectionProjectProfileManager">
  <profiles>
    <profile version="1.0" is_locked="false">
      <option name="myName" value="Project Default"/>
      <option name="myLocal" value="false"/>
      <inspection_tool class="RawUseOfParameterizedType" enabled="true" level="WARNING" enabled_by_default="true">
        <option name="ignoreObjectConstruction" value="false"/>
      </inspection_tool>
      <inspection_tool class="UnusedImport" enabled="true" level="WARNING" enabled_by_default="true"/>
      <inspection_tool class="MissingOverrideAnnotation" enabled="true" level="WARNING" enabled_by_default="true">
        <option name="ignoreObjectMethods" value="false"/>
        <option name="ignoreAnonymousClassMethods" value="false"/>
      </inspection_tool>
    </profile>
  </profiles>
  <option name="PROJECT_PROFILE" value="Project Default"/>
  <option name="USE_PROJECT_PROFILE" value="true"/>
  <version value="1.0"/>
</component>


================================================
FILE: gradle/idea.gradle
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

apply plugin: 'idea'

idea {
    project {
        jdkName = targetCompatibility
        languageLevel = targetCompatibility
        wildcards += 'logback.groovy'

        ipr {
            withXml { provider ->
                def node = provider.asNode()

                def codestyle = new XmlParser().parse(file('gradle/idea-codestyle.xml'))
                node.append(codestyle)

                def inspections = new XmlParser().parse(file('gradle/idea-inspections.xml'))
                node.append(inspections)

                def entrypoints = new XmlParser().parse(file('gradle/idea-entrypoints.xml'))
                node.append(entrypoints)

                def compilerConfig = node.component.find { it.'@name' == 'CompilerConfiguration' }
                compilerConfig.getByName('annotationProcessing').each { compilerConfig.remove(it) }
                def annotationProcessing = compilerConfig.appendNode('annotationProcessing')
                annotationProcessing.appendNode('profile', ['default': true, 'name': 'Default', 'enabled': true]).appendNode('processorPath', ['useClasspath': true])

                def copyrightManager = node.component.find { it.'@name' == 'CopyrightManager' }
                node.remove(copyrightManager)
                def copyright = new XmlParser().parse(file('gradle/idea-copyright.xml'))
                node.append(copyright)

                def vcsDirectoryMappings = node.component.find { it.'@name' == 'VcsDirectoryMappings' }
                def mappings = vcsDirectoryMappings.iterator()
                while (mappings.hasNext()) {
                    mappings.next()
                    mappings.remove()
                }

                def gitRoot = file('.git')
                if (gitRoot.exists()) {
                    vcsDirectoryMappings.appendNode('mapping', ['directory': gitRoot.parentFile, 'vcs': 'Git'])
                }
            }
        }
    }
}


================================================
FILE: gradle/integTest.gradle
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

sourceSets {
    integTest {
        compileClasspath += main.output + test.output
        runtimeClasspath += main.output + test.output
    }
}

configurations {
    integTestCompile.extendsFrom testCompile
    integTestRuntime.extendsFrom testRuntime
}

task integTest(type: Test) {
    testClassesDir = sourceSets.integTest.output.classesDir
    classpath = sourceSets.integTest.runtimeClasspath
    testSrcDirs = []
}

check.dependsOn(integTest)

plugins.withType(org.gradle.plugins.ide.idea.IdeaPlugin) {
    idea {
        module {
            testSourceDirs += sourceSets.integTest.java.srcDirs
            testSourceDirs += sourceSets.integTest.groovy.srcDirs
            testSourceDirs += sourceSets.integTest.resources.srcDirs
            scopes.TEST.plus.add(configurations.integTestCompile)
            scopes.TEST.plus.add(configurations.integTestRuntime)
        }
    }
}

plugins.withType(org.gradle.plugins.ide.eclipse.EclipsePlugin) {
    eclipse {
        classpath {
            plusConfigurations.add(configurations.integTestCompile)
            plusConfigurations.add(configurations.integTestRuntime)
        }
    }
}

task(runTestApp, type: JavaExec) {
    classpath sourceSets.integTest.runtimeClasspath
    main = 'org.springframework.boot.context.embedded.netty.TestApplication'
}


================================================
FILE: gradle/maven.gradle
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

apply plugin: 'maven'

repositories {
    mavenCentral()
}


================================================
FILE: gradle/test.gradle
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

apply plugin: 'jacoco'

apply from: 'gradle/integTest.gradle'
apply from: 'gradle/benchmark.gradle'

task('checkSourceFiles') << {
    def sourceSet = sourceSets.main.java
    for (File srcDir : sourceSet.srcDirs) {
        def tree = fileTree(srcDir).matching(sourceSet.filter)
        def packageDirs = new TreeSet<File>()
        tree.visit { details ->
            if (!details.isDirectory()) {
                packageDirs.add(details.getFile().getParentFile())
            }
        }
        for (File packageDir : packageDirs) {
            def packageInfoFile = new File(packageDir, 'package-info.java')
            assert packageInfoFile.exists(): packageInfoFile.absolutePath + ' is missing. All packages must have a package-info file'

            def sanityTestFile = new File(packageDir.absolutePath.replace('\\', '/').replace('src/main/java', 'src/test/groovy'), 'PackageSanityTest.groovy')
            assert sanityTestFile.exists(): sanityTestFile.absolutePath + ' is missing. All packages must have a Guava package sanity check'
        }
    }
}
compileJava.dependsOn checkSourceFiles


================================================
FILE: gradle/wrapper/gradle-wrapper.properties
================================================
#Mon Nov 24 15:05:30 GMT 2014
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.2-bin.zip


================================================
FILE: gradlew
================================================
#!/usr/bin/env bash

##############################################################################
##
##  Gradle start up script for UN*X
##
##############################################################################

# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""

APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`

# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"

warn ( ) {
    echo "$*"
}

die ( ) {
    echo
    echo "$*"
    echo
    exit 1
}

# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
  CYGWIN* )
    cygwin=true
    ;;
  Darwin* )
    darwin=true
    ;;
  MINGW* )
    msys=true
    ;;
esac

# For Cygwin, ensure paths are in UNIX format before anything is touched.
if $cygwin ; then
    [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
fi

# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
    ls=`ls -ld "$PRG"`
    link=`expr "$ls" : '.*-> \(.*\)$'`
    if expr "$link" : '/.*' > /dev/null; then
        PRG="$link"
    else
        PRG=`dirname "$PRG"`"/$link"
    fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >&-
APP_HOME="`pwd -P`"
cd "$SAVED" >&-

CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar

# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
        # IBM's JDK on AIX uses strange locations for the executables
        JAVACMD="$JAVA_HOME/jre/sh/java"
    else
        JAVACMD="$JAVA_HOME/bin/java"
    fi
    if [ ! -x "$JAVACMD" ] ; then
        die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
    fi
else
    JAVACMD="java"
    which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.

Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi

# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
    MAX_FD_LIMIT=`ulimit -H -n`
    if [ $? -eq 0 ] ; then
        if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
            MAX_FD="$MAX_FD_LIMIT"
        fi
        ulimit -n $MAX_FD
        if [ $? -ne 0 ] ; then
            warn "Could not set maximum file descriptor limit: $MAX_FD"
        fi
    else
        warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
    fi
fi

# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
    GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi

# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
    APP_HOME=`cygpath --path --mixed "$APP_HOME"`
    CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`

    # We build the pattern for arguments to be converted via cygpath
    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
    SEP=""
    for dir in $ROOTDIRSRAW ; do
        ROOTDIRS="$ROOTDIRS$SEP$dir"
        SEP="|"
    done
    OURCYGPATTERN="(^($ROOTDIRS))"
    # Add a user-defined pattern to the cygpath arguments
    if [ "$GRADLE_CYGPATTERN" != "" ] ; then
        OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
    fi
    # Now convert the arguments - kludge to limit ourselves to /bin/sh
    i=0
    for arg in "$@" ; do
        CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
        CHECK2=`echo "$arg"|egrep -c "^-"`                                 ### Determine if an option

        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition
            eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
        else
            eval `echo args$i`="\"$arg\""
        fi
        i=$((i+1))
    done
    case $i in
        (0) set -- ;;
        (1) set -- "$args0" ;;
        (2) set -- "$args0" "$args1" ;;
        (3) set -- "$args0" "$args1" "$args2" ;;
        (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
        (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
        (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
        (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
        (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
        (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
    esac
fi

# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
    JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"

exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"


================================================
FILE: gradlew.bat
================================================
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem  Gradle startup script for Windows
@rem
@rem ##########################################################################

@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal

@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=

set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%

@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome

set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init

echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe

if exist "%JAVA_EXE%" goto init

echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.

goto fail

:init
@rem Get command-line arguments, handling Windowz variants

if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args

:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2

:win9xME_args_slurp
if "x%~1" == "x" goto execute

set CMD_LINE_ARGS=%*
goto execute

:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$

:execute
@rem Setup the command line

set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar

@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%

:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd

:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if  not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1

:mainEnd
if "%OS%"=="Windows_NT" endlocal

:omega


================================================
FILE: settings.gradle
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/*
 * This settings file was auto generated by the Gradle buildInit task
 * by 'dthomas' at '07/08/14 18:11' with Gradle 2.0
 *
 * The settings file is used to specify which projects to include in your build.
 * In a single project build this file can be empty or even removed.
 *
 * Detailed information about configuring a multi-project build in Gradle can be found
 * in the user guide at http://gradle.org/docs/2.0/userguide/multi_project_builds.html
 */

/*
// To declare projects as part of a multi-project build use the 'include' method
include 'shared'
include 'api'
include 'services:webservice'
*/

rootProject.name = 'spring-boot-starter-netty'


================================================
FILE: src/integTest/groovy/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainerAutoConfigurationIntegrationTest.groovy
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty

import org.springframework.boot.SpringApplication
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory
import org.springframework.context.ConfigurableApplicationContext
import spock.lang.Specification

class NettyEmbeddedServletContainerAutoConfigurationIntegrationTest extends Specification {
    def 'application autoconfigures netty factory'() {
        given:
        def String[] args = []
        ConfigurableApplicationContext context = SpringApplication.run(TestApplication, args)

        expect:
        context.getBean(EmbeddedServletContainerFactory) instanceof NettyEmbeddedServletContainerFactory
    }
}


================================================
FILE: src/integTest/java/org/springframework/boot/context/embedded/netty/HttpContentInputStreamBenchmark.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.buffer.Unpooled;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.handler.codec.http.DefaultHttpContent;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * Benchmarks for {@link HttpContentInputStream}.
 */
@State(Scope.Group)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
public class HttpContentInputStreamBenchmark {
    private HttpContentInputStream stream;
    private byte[] b;

    @Param("8192")
    private int size;

    @Setup
    public void setup() {
        stream = new HttpContentInputStream(new EmbeddedChannel());
        b = new byte[size];
    }

    @Benchmark
    @Group("handler")
    public void addContent() {
        stream.addContent(new DefaultHttpContent(Unpooled.buffer(size)));
    }

    @Benchmark
    @Group("handler")
    public int read() throws IOException {
        return stream.read(b);
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(".*" + HttpContentInputStream.class.getSimpleName() + ".*")
                .warmupIterations(5)
                .measurementIterations(5)
                .forks(0)
                .build();

        new Runner(opt).run();
    }
}


================================================
FILE: src/integTest/java/org/springframework/boot/context/embedded/netty/HttpResponseOutputStreamBenchmark.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultHttpResponse;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * Benchmarks for {@link HttpResponseOutputStream}.
 */
@State(Scope.Benchmark)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@BenchmarkMode(Mode.AverageTime)
public class HttpResponseOutputStreamBenchmark {
    private HttpResponseOutputStream stream;
    private byte[] input;

    @Param({"1024", "2048", "4096", "8192", "16384", "32768"})
    public int size;

    @Setup
    public void setup() {
        HttpResponse httpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, false);
        ChannelHandlerContext ctx = new StubChannelHandlerContext();
        NettyEmbeddedContext context = new NettyEmbeddedContext("/", Thread.currentThread().getContextClassLoader(), "Server");
        NettyHttpServletResponse servletResponse = new NettyHttpServletResponse(ctx, context, httpResponse);
        stream = new HttpResponseOutputStream(ctx, servletResponse);
        input = new byte[size];
    }

    @Benchmark
    public void writeByte() throws IOException {
        for (int i = 0; i < size; i++) {
            stream.write(0);
        }
    }

    @Benchmark
    public void writeBytes() throws IOException {
        stream.write(input);
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(".*" + HttpResponseOutputStreamBenchmark.class.getSimpleName() + ".*")
                .warmupIterations(5)
                .measurementIterations(5)
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}


================================================
FILE: src/integTest/java/org/springframework/boot/context/embedded/netty/NettyHttpServletResponseBenchmark.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.handler.codec.http.*;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import java.util.concurrent.TimeUnit;

/**
 * Sample benchmark to check that the Gradle configuration is working.
 */
@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class NettyHttpServletResponseBenchmark {
    private NettyHttpServletResponse response;

    @Setup
    public void setup() {
        StubChannelHandlerContext cxt = new StubChannelHandlerContext();
        HttpResponse httpResponse = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, false);
        NettyEmbeddedContext context = new NettyEmbeddedContext("/", Thread.currentThread().getContextClassLoader(), "Server");
        response = new NettyHttpServletResponse(cxt, context, httpResponse);
    }

    @Benchmark
    public void setContentType() {
        response.setContentType("text/html");
    }

    @Benchmark
    public void setContentTypeHeader() {
        response.setHeader(HttpHeaders.Names.CONTENT_TYPE, "text/html");
    }

    @Benchmark
    public CharSequence getFormattedDate() {
        return response.getFormattedDate();
    }

    public static void main(String[] args) throws RunnerException {
        Options opt = new OptionsBuilder()
                .include(".*" + NettyHttpServletResponseBenchmark.class.getSimpleName() + ".*")
                .warmupIterations(5)
                .measurementIterations(5)
                .forks(1)
                .build();

        new Runner(opt).run();
    }
}


================================================
FILE: src/integTest/java/org/springframework/boot/context/embedded/netty/StubChannelHandlerContext.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.buffer.ByteBufAllocator;
import io.netty.channel.*;
import io.netty.channel.embedded.EmbeddedChannel;
import io.netty.util.Attribute;
import io.netty.util.AttributeKey;
import io.netty.util.ReferenceCounted;
import io.netty.util.concurrent.EventExecutor;

import java.net.SocketAddress;

/**
 * A stub {@link ChannelHandlerContext} for benchmarks, as dynamic mocks introduce far too many side effects.
 */
public class StubChannelHandlerContext implements ChannelHandlerContext {
    private final Channel channel = new EmbeddedChannel();

    @Override
    public ByteBufAllocator alloc() {
        return channel.alloc();
    }

    @Override
    public ChannelFuture write(Object msg) {
        write(msg, null);
        return null;
    }

    @Override
    public ChannelFuture write(Object msg, ChannelPromise promise) {
        if (msg instanceof ReferenceCounted) {
            ((ReferenceCounted) msg).release();
        }
        return null;
    }

    // Default implementations follow

    @Override
    public Channel channel() {
        return null;
    }

    @Override
    public EventExecutor executor() {
        return null;
    }

    @Override
    public String name() {
        return null;
    }

    @Override
    public ChannelHandler handler() {
        return null;
    }

    @Override
    public boolean isRemoved() {
        return false;
    }

    @Override
    public ChannelHandlerContext fireChannelRegistered() {
        return null;
    }

    @Override
    public ChannelHandlerContext fireChannelUnregistered() {
        return null;
    }

    @Override
    public ChannelHandlerContext fireChannelActive() {
        return null;
    }

    @Override
    public ChannelHandlerContext fireChannelInactive() {
        return null;
    }

    @Override
    public ChannelHandlerContext fireExceptionCaught(Throwable cause) {
        return null;
    }

    @Override
    public ChannelHandlerContext fireUserEventTriggered(Object event) {
        return null;
    }

    @Override
    public ChannelHandlerContext fireChannelRead(Object msg) {
        return null;
    }

    @Override
    public ChannelHandlerContext fireChannelReadComplete() {
        return null;
    }

    @Override
    public ChannelHandlerContext fireChannelWritabilityChanged() {
        return null;
    }

    @Override
    public ChannelFuture bind(SocketAddress localAddress) {
        return null;
    }

    @Override
    public ChannelFuture connect(SocketAddress remoteAddress) {
        return null;
    }

    @Override
    public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress) {
        return null;
    }

    @Override
    public ChannelFuture disconnect() {
        return null;
    }

    @Override
    public ChannelFuture close() {
        return null;
    }

    @Override
    public ChannelFuture deregister() {
        return null;
    }

    @Override
    public ChannelFuture bind(SocketAddress localAddress, ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture connect(SocketAddress remoteAddress, ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture connect(SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture disconnect(ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture close(ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture deregister(ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelHandlerContext read() {
        return null;
    }

    @Override
    public ChannelHandlerContext flush() {
        return null;
    }

    @Override
    public ChannelFuture writeAndFlush(Object msg, ChannelPromise promise) {
        return null;
    }

    @Override
    public ChannelFuture writeAndFlush(Object msg) {
        return null;
    }

    @Override
    public ChannelPipeline pipeline() {
        return null;
    }

    @Override
    public ChannelPromise newPromise() {
        return null;
    }

    @Override
    public ChannelProgressivePromise newProgressivePromise() {
        return null;
    }

    @Override
    public ChannelFuture newSucceededFuture() {
        return null;
    }

    @Override
    public ChannelFuture newFailedFuture(Throwable cause) {
        return null;
    }

    @Override
    public ChannelPromise voidPromise() {
        return null;
    }

    @Override
    public <T> Attribute<T> attr(AttributeKey<T> key) {
        return null;
    }

    @Override
    public <T> boolean hasAttr(AttributeKey<T> key) {
        return false;
    }
}


================================================
FILE: src/integTest/java/org/springframework/boot/context/embedded/netty/TestApplication.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.web.WebMvcAutoConfiguration;
import org.springframework.boot.context.embedded.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;

import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.concurrent.Callable;

/**
 * A {@link org.springframework.boot.SpringApplication} harness for integration tests.
 * </p>
 * Implemented in Java to avoid currency issues caused by repeated annotation scanning of Groovy controllers.
 */
@Controller
@EnableAutoConfiguration(exclude = WebMvcAutoConfiguration.class)
@ComponentScan
@EnableWebMvc
class TestApplication {
    private static final String MESSAGE = "Hello, World!";
    private static final Callable<String> MESSAGE_CALLABLE = new Callable<String>() {
        @Override
        public String call() throws Exception {
            return MESSAGE;
        }
    };

    @RequestMapping(value = "/plaintext", produces = "text/plain")
    @ResponseBody
    public String plaintext() {
        return MESSAGE;
    }

    @RequestMapping(value = "/async", produces = "text/plain")
    @ResponseBody
    public Callable<String> async() {
        return MESSAGE_CALLABLE;
    }

    @RequestMapping(value = "/json", produces = "application/json")
    @ResponseBody
    public Message json() {
        return new Message(MESSAGE);
    }

    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @ResponseBody
    public String upload(HttpServletRequest request) throws IOException {
        ServletInputStream inputStream = request.getInputStream();
        int total = 0;
        while (true) {
            byte[] bytes = new byte[8192];
            int read = inputStream.read(bytes);
            if (read == -1) {
                break;
            }
            total += read;
        }
        return "Total bytes received: " + total;
    }

    @RequestMapping("/sleepy")
    @ResponseBody
    public String sleepy() throws InterruptedException {
        int millis = 500;
        Thread.sleep(millis);
        return "Yawn! I slept for " + millis + "ms";
    }

    @Bean
    public ServletRegistrationBean nullServletRegistration() {
        return new ServletRegistrationBean(new NullHttpServlet(), "/null");
    }

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }

    private static class Message {
        private final String message;

        public Message(String message) {
            this.message = message;
        }

        public String getMessage() {
            return message;
        }
    }

    private class NullHttpServlet extends HttpServlet {
        @Override
        protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        }
    }
}


================================================
FILE: src/integTest/resources/logback.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ~ Copyright 2014 the original author or authors.
  ~
  ~ Licensed under the Apache License, Version 2.0 (the "License");
  ~ you may not use this file except in compliance with the License.
  ~ You may obtain a copy of the License at
  ~
  ~   http://www.apache.org/licenses/LICENSE-2.0
  ~
  ~ Unless required by applicable law or agreed to in writing, software
  ~ distributed under the License is distributed on an "AS IS" BASIS,
  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  ~ See the License for the specific language governing permissions and
  ~ limitations under the License.
  ~
  -->
<configuration>
  <include resource="org/springframework/boot/logging/logback/base.xml"/>
  <logger name="org.springframework.boot.context.embedded.netty" level="DEBUG"/>
  <logger name="org.springframework.web" level="INFO"/>
</configuration>


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/AbstractNettyRegistration.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import javax.servlet.FilterConfig;
import javax.servlet.Registration;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
import java.util.Set;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;

/**
 * Abstract class for those classes implementing {@link javax.servlet.Registration} classes and
 * {@link ServletConfig}/{@link FilterConfig}.
 *
 * @author Danny Thomas
 */
class AbstractNettyRegistration implements Registration, Registration.Dynamic, ServletConfig, FilterConfig {
    private final String name;
    private final String className;
    private final NettyEmbeddedContext context;
    protected boolean asyncSupported;

    protected AbstractNettyRegistration(String name, String className, NettyEmbeddedContext context) {
        this.name = checkNotNull(name);
        this.className = checkNotNull(className);
        this.context = checkNotNull(context);
    }

    @Override
    public void setAsyncSupported(boolean isAsyncSupported) {
        asyncSupported = isAsyncSupported;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public String getClassName() {
        return className;
    }

    @Override
    public boolean setInitParameter(String name, String value) {
        checkArgument(name != null, "name may not be null");
        checkArgument(value != null, "value may not be null");
        return false;
    }

    @Override
    public String getFilterName() {
        return name;
    }

    @Override
    public String getServletName() {
        return name;
    }

    @Override
    public ServletContext getServletContext() {
        return context;
    }

    protected NettyEmbeddedContext getNettyContext() {
        return context;
    }

    @Override
    public String getInitParameter(String name) {
        return null;
    }

    @Override
    public Enumeration<String> getInitParameterNames() {
        return Collections.emptyEnumeration();
    }

    @Override
    public Set<String> setInitParameters(Map<String, String> initParameters) {
        return Collections.emptySet();
    }

    @Override
    public Map<String, String> getInitParameters() {
        return Collections.emptyMap();
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/HttpContentInputStream.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import com.google.common.primitives.Ints;
import io.netty.buffer.ByteBuf;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.HttpContent;
import io.netty.handler.codec.http.LastHttpContent;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * A {@link javax.servlet.ServletInputStream} that allows reading from {@link Queue} of {@link HttpContent}, adapting
 * Netty HTTP codec POJOs into a stream readable by servlets.
 *
 * @author Danny Thomas
 */
class HttpContentInputStream extends ServletInputStream {
    private final Channel channel;
    private AtomicBoolean closed;
    private final BlockingQueue<HttpContent> queue;
    private HttpContent current;
    private ReadListener readListener;

    HttpContentInputStream(Channel channel) {
        this.channel = checkNotNull(channel);
        this.closed = new AtomicBoolean();
        queue = new LinkedBlockingQueue<>();
    }

    public void addContent(HttpContent httpContent) {
        checkNotClosed();
        queue.offer(httpContent.retain());
        // TODO limit the number of queued inputs, stop handler from reading from channel
    }

    @Override
    public int readLine(byte[] b, int off, int len) throws IOException {
        checkNotNull(b);
        // TODO use ByteBuf native approach, i.e. bytesBefore, ByteBufProcessor
        return super.readLine(b, off, len);
    }

    @Override
    public boolean isFinished() {
        checkNotClosed();
        return isLastContent() && current.content().readableBytes() == 0;
    }

    private boolean isLastContent() {
        return current instanceof LastHttpContent;
    }

    @Override
    public boolean isReady() {
        checkNotClosed();
        return (current != null && current.content().readableBytes() > 0) || !queue.isEmpty();
    }

    @Override
    public void setReadListener(ReadListener readListener) {
        checkNotClosed();
        checkNotNull(readListener);
        this.readListener = readListener;
    }

    @Override
    public long skip(long n) throws IOException {
        checkNotClosed();
        // TODO implement skip that doesn't read bytes
        return readContent(Ints.checkedCast(n)).readableBytes();
    }

    @Override
    public int available() throws IOException {
        return null == current ? 0 : current.content().readableBytes();
    }

    @Override
    public void close() throws IOException {
        if (closed.compareAndSet(false, true)) {
            // FIXME release the non-written HttpContents?
            queue.clear();
            current = null;
        }
    }

    @Override
    public int read(byte[] b, int off, int len) throws IOException {
        checkNotNull(b);
        if (0 == len) {
            return 0;
        }
        poll();
        if (isFinished()) {
            return -1;
        }
        ByteBuf byteBuf = readContent(len);
        int readableBytes = byteBuf.readableBytes();
        byteBuf.readBytes(b, off, readableBytes);
        return readableBytes - byteBuf.readableBytes();
    }

    @Override
    public int read() throws IOException {
        poll();
        if (isFinished()) {
            return -1;
        }
        return readContent(1).getByte(0);
    }

    private ByteBuf readContent(int length) throws IOException {
        ByteBuf content = current.content();
        if (length < content.readableBytes()) {
            return content.readSlice(length);
        } else {
            return content;
        }
    }

    private void poll() throws IOException {
        checkNotClosed();
        if (null == current || current.content().readableBytes() == 0) {
            boolean blocking = null == readListener;
            while (!isLastContent()) {
                try {
                    // FIXME add appropriate timeout value
                    current = queue.poll(0, TimeUnit.NANOSECONDS);
                } catch (InterruptedException ignored) {
                }
                if (current != null || !blocking) {
                    break;
                }
                if (!channel.isActive()) {
                    throw new IOException("Channel is not active");
                }
            }
        }
    }

    private void checkNotClosed() {
        if (closed.get()) {
            throw new IllegalStateException("Stream is closed");
        }
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/HttpResponseOutputStream.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultLastHttpContent;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponse;

import javax.servlet.ServletOutputStream;
import javax.servlet.WriteListener;
import java.io.IOException;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

/**
 * A buffered {@link ServletOutputStream}, that writes Netty HTTP codec POJOs to the associated
 * {@link ChannelHandlerContext}.
 *
 * @author Danny Thomas
 */
class HttpResponseOutputStream extends ServletOutputStream {
    private static final int DEFAULT_BUFFER_SIZE = 1024 * 8;

    private final ChannelHandlerContext ctx;
    private final NettyHttpServletResponse servletResponse;
    private byte[] buf;
    private int count;
    private boolean closed;
    private WriteListener writeListener;

    HttpResponseOutputStream(ChannelHandlerContext ctx, NettyHttpServletResponse servletResponse) {
        this.ctx = ctx;
        this.servletResponse = servletResponse;
        this.buf = new byte[DEFAULT_BUFFER_SIZE];
    }

    @Override
    public boolean isReady() {
        return true; // TODO implement
    }

    @Override
    public void setWriteListener(WriteListener writeListener) {
        checkNotNull(writeListener);
        // TODO ISE when called more than once
        // TODO ISE when associated request is not async
    }

    @Override
    public void write(byte[] b, int off, int len) throws IOException {
        if (len > count) {
            flushBuffer();
            ByteBuf content = ctx.alloc().buffer(len);
            content.writeBytes(b, off, len);
            writeContent(content, false);
            return;
        }
        writeBufferIfNeeded(len);
        System.arraycopy(b, off, buf, count, len);
        count += len;
    }

    @Override
    public void write(int b) throws IOException {
        writeBufferIfNeeded(1);
        buf[count++] = (byte) b;
    }

    private void writeBufferIfNeeded(int len) throws IOException {
        if (len > buf.length - count) {
            flushBuffer();
        }
    }

    @Override
    public void flush() throws IOException {
        flushBuffer();
    }

    private void flushBuffer() {
        flushBuffer(false);
    }

    private void flushBuffer(boolean lastContent) {
        if (count > 0) {
            ByteBuf content = ctx.alloc().buffer(count);
            content.writeBytes(buf, 0, count);
            count = 0;
            writeContent(content, lastContent);
        } else if (lastContent) {
            writeContent(Unpooled.EMPTY_BUFFER, true);
        }
    }

    private void writeContent(ByteBuf content, boolean lastContent) {
        // TODO block if channel is not writable to avoid heap utilisation
        if (!servletResponse.isCommitted()) {
            writeResponse(lastContent);
        }
        if (content.readableBytes() > 0) {
            assert content.refCnt() == 1;
            ctx.write(content, ctx.voidPromise());
        }
        if (lastContent) {
            HttpResponse nettyResponse = servletResponse.getNettyResponse();
            ChannelFuture future = ctx.write(DefaultLastHttpContent.EMPTY_LAST_CONTENT);
            if (!HttpHeaders.isKeepAlive(nettyResponse)) {
                future.addListener(ChannelFutureListener.CLOSE);
            }
        }
    }

    private void writeResponse(boolean lastContent) {
        HttpResponse response = servletResponse.getNettyResponse();
        // TODO implement exceptions required by http://tools.ietf.org/html/rfc2616#section-4.4
        if (!HttpHeaders.isContentLengthSet(response)) {
            if (lastContent) {
                HttpHeaders.setContentLength(response, count);
            } else {
                HttpHeaders.setTransferEncodingChunked(response);
            }
        }
        ctx.write(response, ctx.voidPromise());
    }

    @Override
    public void close() throws IOException {
        if (closed) {
            return;
        }
        closed = true;
        try {
            flushBuffer(true);
            ctx.flush();
        } finally {
            buf = null;
        }
    }

    void resetBuffer() {
        assert !servletResponse.isCommitted();
        count = 0;
    }

    int getBufferSize() {
        return buf.length;
    }

    void setBufferSize(int size) {
        assert !servletResponse.isCommitted();
        checkState(count == 0, "Response body content has been written");
        buf = new byte[size];
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyAsyncContext.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import com.google.common.collect.ImmutableList;
import io.netty.channel.ChannelHandlerContext;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Netty {@link AsyncContext}.
 *
 * @author Danny Thomas
 */
class NettyAsyncContext implements AsyncContext {
    private ServletRequest servletRequest;
    private final ChannelHandlerContext ctx;
    private ServletResponse servletResponse;
    private boolean asyncStarted;
    private List<AsyncListener> listeners;

    NettyAsyncContext(ServletRequest servletRequest, ChannelHandlerContext ctx) {
        this.servletRequest = servletRequest;
        this.ctx = ctx;
        this.listeners = new ArrayList<>();
    }

    AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) {
        this.servletRequest = servletRequest;
        this.servletResponse = servletResponse;
        asyncStarted = true;
        return this;
    }

    @Override
    public ServletRequest getRequest() {
        return servletRequest;
    }

    @Override
    public ServletResponse getResponse() {
        return servletResponse;
    }

    @Override
    public boolean hasOriginalRequestAndResponse() {
        return true;
    }

    @Override
    public void dispatch() {
        if (servletRequest instanceof HttpServletRequest) {
            HttpServletRequest request = (HttpServletRequest) servletRequest;
            String path = request.getServletPath();
            String pathInfo = request.getPathInfo();
            if (null != pathInfo) {
                path += pathInfo;
            }
            dispatch(path);
        }
    }

    @Override
    public void dispatch(String path) {
        dispatch(servletRequest.getServletContext(), path);
    }

    @Override
    public void dispatch(ServletContext context, String path) {
        final HttpServletRequest httpRequest = (HttpServletRequest) servletRequest;
        httpRequest.setAttribute(ASYNC_CONTEXT_PATH, httpRequest.getContextPath());
        httpRequest.setAttribute(ASYNC_PATH_INFO, httpRequest.getPathInfo());
        httpRequest.setAttribute(ASYNC_QUERY_STRING, httpRequest.getQueryString());
        httpRequest.setAttribute(ASYNC_REQUEST_URI, httpRequest.getRequestURI());
        httpRequest.setAttribute(ASYNC_SERVLET_PATH, httpRequest.getServletPath());
        final NettyRequestDispatcher dispatcher = (NettyRequestDispatcher) context.getRequestDispatcher(path);
        ctx.executor().submit(new Runnable() {
            @Override
            public void run() {
                try {
                    dispatcher.dispatch(httpRequest, servletResponse);
                    // TODO is this right?
                    for (AsyncListener listener : ImmutableList.copyOf(listeners)) {
                        listener.onComplete(new AsyncEvent(NettyAsyncContext.this));
                    }
                } catch (ServletException | IOException e) {
                    // TODO notify listeners
                    e.printStackTrace();
                }
            }
        });
    }

    @Override
    public void complete() {
        try {
            servletResponse.getOutputStream().close();
        } catch (IOException e) {
            // TODO notify listeners
            e.printStackTrace();
        }
    }

    @Override
    public void start(Runnable run) {
        ctx.executor().submit(run, Object.class);
    }

    @Override
    public void addListener(AsyncListener listener) {
        listeners.add(listener);
    }

    @Override
    public void addListener(AsyncListener listener, ServletRequest servletRequest, ServletResponse servletResponse) {

    }

    @Override
    public <T extends AsyncListener> T createListener(Class<T> clazz) throws ServletException {
        return null;
    }

    @Override
    public void setTimeout(long timeout) {

    }

    @Override
    public long getTimeout() {
        return 0;
    }

    public boolean isAsyncStarted() {
        return asyncStarted;
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedContext.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import com.google.common.collect.ImmutableMap;
import io.netty.util.AsciiString;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.servlet.*;
import javax.servlet.descriptor.JspConfigDescriptor;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;

/**
 * Netty servlet bridge {@link ServletContext} implementation.
 */
class NettyEmbeddedContext implements ServletContext {
    private final Log logger = LogFactory.getLog(NettyEmbeddedContext.class);

    private final String contextPath;
    private final ClassLoader classLoader;
    private final Map<String, NettyServletRegistration> servlets = new HashMap<>();
    private final Map<String, String> servletMappings = new HashMap<>();
    private final Map<String, NettyFilterRegistration> filters = new HashMap<>();
    private final AsciiString serverInfo;
    private volatile boolean initialised;

    NettyEmbeddedContext(String contextPath, ClassLoader classLoader, String serverInfo) {
        this.contextPath = contextPath;
        this.classLoader = classLoader;
        this.serverInfo = new AsciiString(serverInfo);
    }

    public void setInitialised(boolean initialised) {
        this.initialised = initialised;
    }

    public boolean isInitialised() {
        return initialised;
    }

    public void checkNotInitialised() {
        checkState(!isInitialised(), "This method may not be called after the context has been initialised");
    }

    public void addServletMapping(String urlPattern, String name) {
        checkNotInitialised();
        servletMappings.put(urlPattern, checkNotNull(name));
    }

    public void addFilterMapping(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String urlPattern) {
        checkNotInitialised();
        // TODO
    }

    @Override
    public ServletContext getContext(String uripath) {
        return null;
    }

    @Override
    public String getContextPath() {
        return contextPath;
    }

    @Override
    public int getMajorVersion() {
        return 0;
    }

    @Override
    public int getMinorVersion() {
        return 0;
    }

    @Override
    public int getEffectiveMajorVersion() {
        return 0;
    }

    @Override
    public int getEffectiveMinorVersion() {
        return 0;
    }

    @Override
    public String getMimeType(String file) {
        return null;
    }

    @Override
    public Set<String> getResourcePaths(String path) {
        return null;
    }

    @Override
    public URL getResource(String path) throws MalformedURLException {
        return null;
    }

    @Override
    public InputStream getResourceAsStream(String path) {
        return null;
    }

    @Override
    public RequestDispatcher getRequestDispatcher(String path) {
        // FIXME proper path matching
        String servletName = servletMappings.get(path);
        if (servletName == null) {
            servletName = servletMappings.get("/");
        }
        Servlet servlet = null;
        try {
            servlet = null == servletName ? null : servlets.get(servletName).getServlet();
            if (servlet == null) {
                return null;
            }
            // FIXME proper path matching
            List<Filter> filters = new ArrayList<>();
            for (NettyFilterRegistration registration : this.filters.values()) {
                filters.add(registration.getFilter());
            }
            FilterChain filterChain = new SimpleFilterChain(servlet, filters);
            return new NettyRequestDispatcher(this, filterChain);
        } catch (ServletException e) {
            // TODO log exception
            return null;
        }
    }

    @Override
    public RequestDispatcher getNamedDispatcher(String name) {
        return null;
    }

    @Override
    public Servlet getServlet(String name) throws ServletException {
        return servlets.get(name).getServlet();
    }

    @Override
    public Enumeration<Servlet> getServlets() {
        return Collections.emptyEnumeration();
    }

    @Override
    public Enumeration<String> getServletNames() {
        return Collections.emptyEnumeration();
    }

    @Override
    public void log(String msg) {
        logger.info(msg);
    }

    @Override
    public void log(Exception exception, String msg) {
        logger.error(msg, exception);
    }

    @Override
    public void log(String message, Throwable throwable) {
        logger.error(message, throwable);
    }

    @Override
    public String getRealPath(String path) {
        return null;
    }

    @Override
    public String getServerInfo() {
        return serverInfo.toString();
    }

    AsciiString getServerInfoAscii() {
        return serverInfo;
    }

    @Override
    public String getInitParameter(String name) {
        return null;
    }

    @Override
    public Enumeration<String> getInitParameterNames() {
        return Collections.emptyEnumeration();
    }

    @Override
    public boolean setInitParameter(String name, String value) {
        return false;
    }

    @Override
    public Object getAttribute(String name) {
        return null;
    }

    @Override
    public Enumeration<String> getAttributeNames() {
        return Collections.emptyEnumeration();
    }

    @Override
    public void setAttribute(String name, Object object) {

    }

    @Override
    public void removeAttribute(String name) {

    }

    @Override
    public String getServletContextName() {
        return null;
    }

    @Override
    public ServletRegistration.Dynamic addServlet(String servletName, String className) {
        return addServlet(servletName, className, null);
    }

    @Override
    public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
        return addServlet(servletName, servlet.getClass().getName(), servlet);
    }

    @Override
    public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) {
        return addServlet(servletName, servletClass.getName());
    }

    private ServletRegistration.Dynamic addServlet(String servletName, String className, Servlet servlet) {
        NettyServletRegistration servletRegistration = new NettyServletRegistration(this, servletName, className, servlet);
        servlets.put(servletName, servletRegistration);
        return servletRegistration;
    }

    @Override
    public <T extends Servlet> T createServlet(Class<T> c) throws ServletException {
        return null;
    }

    @Override
    public ServletRegistration getServletRegistration(String servletName) {
        return null;
    }

    @Override
    public Map<String, ? extends ServletRegistration> getServletRegistrations() {
        return null;
    }

    @Override
    public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, String className) {
        return addFilter(filterName, className, null);
    }

    @Override
    public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
        return addFilter(filterName, filter.getClass().getName(), filter);
    }

    private javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, String className, Filter filter) {
        NettyFilterRegistration filterRegistration = new NettyFilterRegistration(this, filterName, className, filter);
        filters.put(filterName, filterRegistration);
        return filterRegistration;
    }


    @Override
    public javax.servlet.FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) {
        return addFilter(filterName, filterClass.getName());
    }

    @Override
    public <T extends Filter> T createFilter(Class<T> c) throws ServletException {
        return null;
    }

    @Override
    public javax.servlet.FilterRegistration getFilterRegistration(String filterName) {
        return filters.get(filterName);
    }

    @Override
    public Map<String, ? extends javax.servlet.FilterRegistration> getFilterRegistrations() {
        return ImmutableMap.copyOf(filters);
    }

    @Override
    public SessionCookieConfig getSessionCookieConfig() {
        return null;
    }

    @Override
    public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes) throws IllegalStateException, IllegalArgumentException {

    }

    @Override
    public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
        return null;
    }

    @Override
    public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
        return null;
    }

    @Override
    public void addListener(String className) {

    }

    @Override
    public <T extends EventListener> void addListener(T t) {

    }

    @Override
    public void addListener(Class<? extends EventListener> listenerClass) {

    }

    @Override
    public <T extends EventListener> T createListener(Class<T> c) throws ServletException {
        return null;
    }

    @Override
    public void declareRoles(String... roleNames) {

    }

    @Override
    public String getVirtualServerName() {
        return null;
    }

    @Override
    public ClassLoader getClassLoader() {
        return classLoader;
    }

    @Override
    public JspConfigDescriptor getJspConfigDescriptor() {
        return null;
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainer.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import com.google.common.base.StandardSystemProperty;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.epoll.EpollChannelOption;
import io.netty.channel.epoll.EpollEventLoopGroup;
import io.netty.channel.epoll.EpollServerSocketChannel;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.util.concurrent.DefaultEventExecutorGroup;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerException;

import java.net.InetSocketAddress;

/**
 * An {@link EmbeddedServletContainer} used to control an embedded Netty instance, that bridges to
 * {@link javax.servlet.http.HttpServletRequest} and from {@link javax.servlet.http.HttpServletResponse}
 * to Netty HTTP codec {@link io.netty.handler.codec.http.HttpMessage}s.
 * <p>
 * This is a minimal Servlet 3.1 implementation to provide for the opinionated embedded servlet container model for
 * Spring Boot, supporting a single context, runtime {@link javax.servlet.Registration} only, and no default or JSP
 * servlets.
 * <p>
 * This class should be created using the {@link NettyEmbeddedServletContainerFactory}.
 *
 * @author Danny Thomas
 */
public class NettyEmbeddedServletContainer implements EmbeddedServletContainer {
    private final Log logger = LogFactory.getLog(getClass());
    private final InetSocketAddress address;
    private final NettyEmbeddedContext context;

    private EventLoopGroup bossGroup;
    private EventLoopGroup workerGroup;
    private DefaultEventExecutorGroup servletExecutor;

    public NettyEmbeddedServletContainer(InetSocketAddress address, NettyEmbeddedContext context) {
        this.address = address;
        this.context = context;
    }

    @Override
    public void start() throws EmbeddedServletContainerException {
        ServerBootstrap b = new ServerBootstrap();
        groups(b);
        servletExecutor = new DefaultEventExecutorGroup(50);
        b.childHandler(new NettyEmbeddedServletInitializer(servletExecutor, context));

        // Don't yet need the complexity of lifecycle state, listeners etc, so tell the context it's initialised here
        context.setInitialised(true);

        ChannelFuture future = b.bind(address).awaitUninterruptibly();
        //noinspection ThrowableResultOfMethodCallIgnored
        Throwable cause = future.cause();
        if (null != cause) {
            throw new EmbeddedServletContainerException("Could not start Netty server", cause);
        }
        logger.info(context.getServerInfo() + " started on port: " + getPort());
    }

    private void groups(ServerBootstrap b) {
        if (StandardSystemProperty.OS_NAME.value().equals("Linux")) {
            bossGroup = new EpollEventLoopGroup(1);
            workerGroup = new EpollEventLoopGroup();
            b.channel(EpollServerSocketChannel.class)
                    .group(bossGroup, workerGroup)
                    .option(EpollChannelOption.TCP_CORK, true);
        } else {
            bossGroup = new NioEventLoopGroup(1);
            workerGroup = new NioEventLoopGroup();
            b.channel(NioServerSocketChannel.class)
                    .group(bossGroup, workerGroup);
        }
        b.option(ChannelOption.TCP_NODELAY, true)
                .option(ChannelOption.SO_REUSEADDR, true)
                .option(ChannelOption.SO_BACKLOG, 100);
        logger.info("Bootstrap configuration: " + b.toString());
    }

    @Override
    public void stop() throws EmbeddedServletContainerException {
        try {
            if (null != bossGroup) {
                bossGroup.shutdownGracefully().await();
            }
            if (null != workerGroup) {
                workerGroup.shutdownGracefully().await();
            }
            if (null != servletExecutor) {
                servletExecutor.shutdownGracefully().await();
            }
        } catch (InterruptedException e) {
            throw new EmbeddedServletContainerException("Container stop interrupted", e);
        }
    }

    @Override
    public int getPort() {
        return address.getPort();
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainerAutoConfiguration.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.bootstrap.Bootstrap;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
import org.springframework.boot.autoconfigure.condition.SearchStrategy;
import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration.EmbeddedServletContainerCustomizerBeanPostProcessorRegistrar;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;

/**
 * {@link org.springframework.boot.autoconfigure.EnableAutoConfiguration Auto-configuration} for an embedded servlet containers.
 *
 * @author Danny Thomas
 */
@Order(Ordered.HIGHEST_PRECEDENCE)
@Configuration
@ConditionalOnWebApplication
@Import(EmbeddedServletContainerCustomizerBeanPostProcessorRegistrar.class)
public class NettyEmbeddedServletContainerAutoConfiguration {
    @Configuration
    @ConditionalOnClass({Bootstrap.class})
    @ConditionalOnMissingBean(value = EmbeddedServletContainerFactory.class, search = SearchStrategy.CURRENT)
    public static class EmbeddedNetty {
        @Bean
        public NettyEmbeddedServletContainerFactory nettyEmbeddedServletContainerFactory() {
            return new NettyEmbeddedServletContainerFactory();
        }
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainerFactory.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.bootstrap.Bootstrap;
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.ServletContextInitializer;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ClassUtils;

import javax.servlet.ServletException;
import java.net.InetSocketAddress;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Random;

/**
 * An {@link EmbeddedServletContainerFactory} that can be used to create {@link NettyEmbeddedServletContainer}s.
 *
 * @author Danny Thomas
 */
public class NettyEmbeddedServletContainerFactory extends AbstractEmbeddedServletContainerFactory implements ResourceLoaderAware {
    public static final String SERVER_INFO = "netty/servlet";
    private ResourceLoader resourceLoader;

    @Override
    public EmbeddedServletContainer getEmbeddedServletContainer(ServletContextInitializer... initializers) {
        ClassLoader parentClassLoader = resourceLoader != null ? resourceLoader.getClassLoader() : ClassUtils.getDefaultClassLoader();
        Package nettyPackage = Bootstrap.class.getPackage();
        String title = nettyPackage.getImplementationTitle();
        String version = nettyPackage.getImplementationVersion();
        logger.info("Running with " + title + " " + version);
        NettyEmbeddedContext context = new NettyEmbeddedContext(getContextPath(), new URLClassLoader(new URL[]{}, parentClassLoader), SERVER_INFO);
        if (isRegisterDefaultServlet()) {
            logger.warn("This container does not support a default servlet");
        }
        if (isRegisterJspServlet()) {
            logger.warn("This container does not support a JSP servlet");
        }
        for (ServletContextInitializer initializer : initializers) {
            try {
                initializer.onStartup(context);
            } catch (ServletException e) {
                throw new RuntimeException(e);
            }
        }
        int port = getPort() > 0 ? getPort() : new Random().nextInt(65535 - 1024) + 1024;
        InetSocketAddress address = new InetSocketAddress(port);
        logger.info("Server initialized with port: " + port);
        return new NettyEmbeddedServletContainer(address, context);
    }

    @Override
    public void setResourceLoader(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletInitializer.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.util.concurrent.EventExecutorGroup;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * {@link ChannelInitializer} for {@link org.springframework.boot.context.embedded.netty.NettyEmbeddedServletContainer}.
 *
 * @author Danny Thomas
 */
class NettyEmbeddedServletInitializer extends ChannelInitializer<SocketChannel> {
    private final EventExecutorGroup servletExecutor;
    private final RequestDispatcherHandler requestDispatcherHandler;
    private final NettyEmbeddedContext servletContext;

    NettyEmbeddedServletInitializer(EventExecutorGroup servletExecutor, NettyEmbeddedContext servletContext) {
        this.servletContext = servletContext;
        this.servletExecutor = checkNotNull(servletExecutor);
        requestDispatcherHandler = new RequestDispatcherHandler(servletContext);
    }

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline p = ch.pipeline();
        p.addLast("codec", new HttpServerCodec(4096, 8192, 8192, false));
        p.addLast("servletInput", new ServletContentHandler(servletContext));
        p.addLast(servletExecutor, "filterChain", requestDispatcherHandler);
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyFilterRegistration.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletException;
import java.util.Collection;
import java.util.EnumSet;

/**
 * A {@link org.springframework.boot.context.embedded.netty.NettyEmbeddedContext} {@link javax.servlet.FilterRegistration}.
 *
 * @author Danny Thomas
 */
class NettyFilterRegistration extends AbstractNettyRegistration implements FilterRegistration.Dynamic {
    private volatile boolean initialised;
    private Filter filter;

    NettyFilterRegistration(NettyEmbeddedContext context, String filterName, String className, Filter filter) {
        super(filterName, className, context);
        this.filter = filter;
    }

    public Filter getFilter() throws ServletException {
        if (!initialised) {
            synchronized (this) {
                if (!initialised) {
                    if (null == filter) {
                        try {
                            filter = (Filter) Class.forName(getClassName()).newInstance();
                        } catch (Exception e) {
                            throw new ServletException(e);
                        }
                    }
                    filter.init(this);
                    initialised = true;
                }
            }
        }
        return filter;
    }

    @Override
    public void addMappingForServletNames(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... servletNames) {

    }

    @Override
    public Collection<String> getServletNameMappings() {
        return null;
    }

    @Override
    public void addMappingForUrlPatterns(EnumSet<DispatcherType> dispatcherTypes, boolean isMatchAfter, String... urlPatterns) {
        NettyEmbeddedContext context = getNettyContext();
        for (String urlPattern : urlPatterns) {
            context.addFilterMapping(dispatcherTypes, isMatchAfter, urlPattern);
        }
    }

    @Override
    public Collection<String> getUrlPatternMappings() {
        return null;
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyHttpServletRequest.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpRequest;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.Principal;
import java.util.*;

/**
 * {@link HttpServletRequest} wrapper for Netty's {@link HttpRequest}.
 *
 * @author Danny Thomas
 */
class NettyHttpServletRequest implements HttpServletRequest {
    public static final String DISPATCHER_TYPE = NettyRequestDispatcher.class.getName() + ".DISPATCHER_TYPE";

    private final ChannelHandlerContext ctx;
    private final NettyEmbeddedContext servletContext;
    private final HttpRequest request;
    private final ServletInputStream inputStream;
    private final Map<String, Object> attributes;

    private boolean asyncSupported = true;
    private NettyAsyncContext asyncContext;
    private HttpServletResponse servletResponse;

    NettyHttpServletRequest(ChannelHandlerContext ctx, NettyEmbeddedContext servletContext, HttpRequest request, HttpServletResponse servletResponse, ServletInputStream inputStream) {
        this.ctx = ctx;
        this.servletContext = servletContext;
        this.request = request;
        this.servletResponse = servletResponse;
        this.inputStream = inputStream;
        this.attributes = new HashMap<>();
    }

    HttpRequest getNettyRequest() {
        return request;
    }

    @Override
    public String getAuthType() {
        return null;
    }

    @Override
    public Cookie[] getCookies() {
        return new Cookie[0];
    }

    @Override
    public long getDateHeader(String name) {
        return 0;
    }

    @Override
    public String getHeader(String name) {
        return null;
    }

    @Override
    public Enumeration<String> getHeaders(String name) {
        return Collections.emptyEnumeration();
    }

    @Override
    public Enumeration<String> getHeaderNames() {
        return Collections.emptyEnumeration();
    }

    @Override
    public int getIntHeader(String name) {
        return 0;
    }

    @Override
    public String getMethod() {
        return request.method().name();
    }

    @Override
    public String getPathInfo() {
        return null;
    }

    @Override
    public String getPathTranslated() {
        return null;
    }

    @Override
    public String getContextPath() {
        String requestURI = getRequestURI();
        // FIXME implement properly
        return "/".equals(requestURI) ? "" : requestURI;
    }

    @Override
    public String getQueryString() {
        return null;
    }

    @Override
    public String getRemoteUser() {
        return null;
    }

    @Override
    public boolean isUserInRole(String role) {
        return false;
    }

    @Override
    public Principal getUserPrincipal() {
        return null;
    }

    @Override
    public String getRequestedSessionId() {
        return null;
    }

    @Override
    public String getRequestURI() {
        return request.uri();
    }

    @Override
    public StringBuffer getRequestURL() {
        return null;
    }

    @Override
    public String getServletPath() {
        return getRequestURI();
    }

    @Override
    public HttpSession getSession(boolean create) {
        return null;
    }

    @Override
    public HttpSession getSession() {
        return null;
    }

    @Override
    public String changeSessionId() {
        return null;
    }

    @Override
    public boolean isRequestedSessionIdValid() {
        return false;
    }

    @Override
    public boolean isRequestedSessionIdFromCookie() {
        return false;
    }

    @Override
    public boolean isRequestedSessionIdFromURL() {
        return false;
    }

    @Override
    public boolean isRequestedSessionIdFromUrl() {
        return false;
    }

    @Override
    public boolean authenticate(HttpServletResponse response) throws IOException, ServletException {
        return false;
    }

    @Override
    public void login(String username, String password) throws ServletException {

    }

    @Override
    public void logout() throws ServletException {

    }

    @Override
    public Collection<Part> getParts() throws IOException, IllegalStateException, ServletException {
        return null;
    }

    @Override
    public Part getPart(String name) throws IOException, IllegalStateException, ServletException {
        return null;
    }

    @Override
    public <T extends HttpUpgradeHandler> T upgrade(Class<T> handlerClass) throws IOException, ServletException {
        return null;
    }

    @Override
    public Object getAttribute(String name) {
        synchronized (attributes) {
            return attributes.get(name);
        }
    }

    @Override
    public Enumeration<String> getAttributeNames() {
        synchronized (attributes) {
            return Collections.enumeration(attributes.keySet());
        }
    }

    @Override
    public String getCharacterEncoding() {
        return null;
    }

    @Override
    public void setCharacterEncoding(String env) throws UnsupportedEncodingException {

    }

    @Override
    public int getContentLength() {
        return 0;
    }

    @Override
    public long getContentLengthLong() {
        return 0;
    }

    @Override
    public String getContentType() {
        return null;
    }

    @Override
    public ServletInputStream getInputStream() throws IOException {
        return inputStream;
    }

    @Override
    public String getParameter(String name) {
        return null;
    }

    @Override
    public Enumeration<String> getParameterNames() {
        return null;
    }

    @Override
    public String[] getParameterValues(String name) {
        return new String[0];
    }

    @Override
    public Map<String, String[]> getParameterMap() {
        return null;
    }

    @Override
    public String getProtocol() {
        return request.protocolVersion().protocolName();
    }

    @Override
    public String getScheme() {
        return null;
    }

    @Override
    public String getServerName() {
        return null;
    }

    @Override
    public int getServerPort() {
        return 0;
    }

    @Override
    public BufferedReader getReader() throws IOException {
        return null;
    }

    @Override
    public String getRemoteAddr() {
        return null;
    }

    @Override
    public String getRemoteHost() {
        return null;
    }

    @Override
    public void setAttribute(String name, Object o) {
        synchronized (attributes) {
            attributes.put(name, o);
        }
    }

    @Override
    public void removeAttribute(String name) {
        synchronized (attributes) {
            attributes.remove(name);
        }
    }

    @Override
    public Locale getLocale() {
        return null;
    }

    @Override
    public Enumeration<Locale> getLocales() {
        return null;
    }

    @Override
    public boolean isSecure() {
        return false;
    }

    @Override
    public RequestDispatcher getRequestDispatcher(String path) {
        return null;
    }

    @Override
    public String getRealPath(String path) {
        return null;
    }

    @Override
    public int getRemotePort() {
        return 0;
    }

    @Override
    public String getLocalName() {
        return null;
    }

    @Override
    public String getLocalAddr() {
        return null;
    }

    @Override
    public int getLocalPort() {
        return 0;
    }

    @Override
    public ServletContext getServletContext() {
        return servletContext;
    }

    @Override
    public AsyncContext startAsync() {
        return startAsync(this, null);
    }

    @Override
    public AsyncContext startAsync(ServletRequest servletRequest, ServletResponse servletResponse) {
        return ((NettyAsyncContext) getAsyncContext()).startAsync(servletRequest, servletResponse);
    }

    @Override
    public boolean isAsyncStarted() {
        return null != asyncContext && asyncContext.isAsyncStarted();
    }

    void setAsyncSupported(boolean asyncSupported) {
        this.asyncSupported = asyncSupported;
    }

    @Override
    public boolean isAsyncSupported() {
        return asyncSupported;
    }

    @Override
    public AsyncContext getAsyncContext() {
        if (null == asyncContext) {
            asyncContext = new NettyAsyncContext(this, ctx);
        }
        return asyncContext;
    }

    @Override
    public DispatcherType getDispatcherType() {
        return attributes.containsKey(DISPATCHER_TYPE) ? (DispatcherType) attributes.get(DISPATCHER_TYPE) : DispatcherType.REQUEST;
    }

    public ServletResponse getServletResponse() {
        return servletResponse;
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyHttpServletResponse.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Charsets;
import com.google.common.base.Optional;
import com.google.common.net.MediaType;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.concurrent.FastThreadLocal;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import static com.google.common.base.Preconditions.checkState;

/**
 * {@link HttpServletResponse} wrapper for Netty's {@link HttpResponse}.
 *
 * @author Danny Thomas
 */
class NettyHttpServletResponse implements HttpServletResponse {
    private static final FastThreadLocal<DateFormat> FORMAT = new FastThreadLocal<DateFormat>() {
        @Override
        protected DateFormat initialValue() {
            return new SimpleDateFormat("E, dd MMM yyyy HH:mm:ss z");
        }
    };

    private static final Locale DEFAULT_LOCALE = Locale.getDefault();
    private static final String DEFAULT_CHARACTER_ENCODING = Charsets.ISO_8859_1.name();

    private final NettyEmbeddedContext servletContext;
    private HttpResponse response;
    private HttpResponseOutputStream outputStream;
    private boolean usingOutputStream;
    private PrintWriter writer;
    private boolean committed;
    private List<Cookie> cookies;
    private String contentType;
    private String characterEncoding = DEFAULT_CHARACTER_ENCODING;
    private Locale locale;

    NettyHttpServletResponse(ChannelHandlerContext ctx, NettyEmbeddedContext servletContext, HttpResponse response) {
        this.servletContext = servletContext;
        this.response = response;
        this.outputStream = new HttpResponseOutputStream(ctx, this);
        cookies = new ArrayList<>();
    }

    /**
     * Get a Netty {@link HttpResponse}, committing the {@link HttpServletResponse}.
     */
    public HttpResponse getNettyResponse() {
        if (committed) {
            return response;
        }
        committed = true;
        HttpHeaders headers = response.headers();
        if (null != contentType) {
            String value = null == characterEncoding ? contentType : contentType + "; charset=" + characterEncoding;
            headers.set(HttpHeaders.Names.CONTENT_TYPE, value);
        }
        CharSequence date = getFormattedDate();
        headers.set(HttpHeaders.Names.DATE, date);
        headers.set(HttpHeaders.Names.SERVER, servletContext.getServerInfoAscii());
        // TODO cookies
        return response;
    }

    @VisibleForTesting
    CharSequence getFormattedDate() {
        return HttpHeaders.newEntity(FORMAT.get().format(new Date()));
    }

    @Override
    public void addCookie(Cookie cookie) {
        cookies.add(cookie);
    }

    @Override
    public boolean containsHeader(String name) {
        return response.headers().contains(name);
    }

    @Override
    public String encodeURL(String url) {
        return null;
    }

    @Override
    public String encodeRedirectURL(String url) {
        return null;
    }

    @Override
    public String encodeUrl(String url) {
        return null;
    }

    @Override
    public String encodeRedirectUrl(String url) {
        return null;
    }

    @Override
    public void sendError(int sc, String msg) throws IOException {
        checkNotCommitted();
        response.setStatus(new HttpResponseStatus(sc, msg));
    }

    @Override
    public void sendError(int sc) throws IOException {
        checkNotCommitted();
        response.setStatus(HttpResponseStatus.valueOf(sc));
    }

    @Override
    public void sendRedirect(String location) throws IOException {
        checkNotCommitted();
        // TODO implement
    }

    @Override
    public void setDateHeader(String name, long date) {
        response.headers().set(name, date);
    }

    @Override
    public void addDateHeader(String name, long date) {
        response.headers().add(name, date);
    }

    @Override
    public void setHeader(String name, String value) {
        if (setHeaderField(name, value)) {
            return;
        }
        response.headers().set(name, value);
    }

    private boolean setHeaderField(String name, String value) {
        // Handle headers that shouldn't be set directly, and are instance fields
        char c = name.charAt(0);
        if ('C' == c || 'c' == c) {
            if (HttpHeaders.Names.CONTENT_TYPE.equalsIgnoreCase(name)) {
                setContentType(value);
                return true;
            }
            // TODO Content-Language?
        }
        return false;
    }

    @Override
    public void addHeader(String name, String value) {
        if (setHeaderField(name, value)) {
            return;
        }
        response.headers().add(name, value);
    }

    @Override
    public void setIntHeader(String name, int value) {
        response.headers().set(name, value);
    }

    @Override
    public void addIntHeader(String name, int value) {
        response.headers().add(name, value);
    }

    @Override
    public void setStatus(int sc) {
        response.setStatus(HttpResponseStatus.valueOf(sc));
    }

    @Override
    public void setStatus(int sc, String sm) {
        response.setStatus(new HttpResponseStatus(sc, sm));
    }

    @Override
    public int getStatus() {
        return response.status().code();
    }

    @Override
    public String getHeader(String name) {
        return response.headers().get(name);
    }

    @Override
    public Collection<String> getHeaders(String name) {
        return response.headers().getAll(name);
    }

    @Override
    public Collection<String> getHeaderNames() {
        return response.headers().names();
    }

    @Override
    public String getCharacterEncoding() {
        return characterEncoding;
    }

    @Override
    public String getContentType() {
        return contentType;
    }

    @Override
    public ServletOutputStream getOutputStream() throws IOException {
        checkState(!hasWriter(), "getWriter has already been called for this response");
        usingOutputStream = true;
        return outputStream;
    }

    @Override
    public PrintWriter getWriter() throws IOException {
        checkState(!usingOutputStream, "getOutputStream has already been called for this response");
        if (!hasWriter()) {
            writer = new PrintWriter(outputStream);
        }
        return writer;
    }

    @Override
    public void setCharacterEncoding(String charset) {
        if (hasWriter()) {
            return;
        }
        characterEncoding = charset;
    }

    @Override
    public void setContentType(String type) {
        if (isCommitted()) {
            return;
        }
        if (hasWriter()) {
            return;
        }
        if (null == type) {
            contentType = null;
            return;
        }
        MediaType mediaType = MediaType.parse(type);
        Optional<Charset> charset = mediaType.charset();
        if (charset.isPresent()) {
            setCharacterEncoding(charset.get().name());
        }
        contentType = mediaType.type() + '/' + mediaType.subtype();
    }

    private boolean hasWriter() {
        return null != writer;
    }

    @Override
    public void setContentLength(int len) {
        HttpHeaders.setContentLength(response, len);
    }

    @Override
    public void setContentLengthLong(long len) {
        HttpHeaders.setContentLength(response, len);
    }

    @Override
    public void setBufferSize(int size) {
        checkNotCommitted();
        outputStream.setBufferSize(size);
    }

    @Override
    public int getBufferSize() {
        return outputStream.getBufferSize();
    }

    @Override
    public void flushBuffer() throws IOException {
        checkNotCommitted();
        outputStream.flush();
    }

    @Override
    public void resetBuffer() {
        checkNotCommitted();
        outputStream.resetBuffer();
    }

    @Override
    public boolean isCommitted() {
        return committed;
    }

    void checkNotCommitted() {
        checkState(!committed, "Cannot perform this operation after response has been committed");
    }

    @Override
    public void reset() {
        resetBuffer();
        usingOutputStream = false;
        writer = null;
    }

    @Override
    public void setLocale(Locale loc) {
        locale = loc;
    }

    @Override
    public Locale getLocale() {
        return null == locale ? DEFAULT_LOCALE : locale;
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyRequestDispatcher.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import javax.servlet.*;
import java.io.IOException;

/**
 * @author Danny Thomas
 */
class NettyRequestDispatcher implements RequestDispatcher {
    private final ServletContext context;
    private final FilterChain filterChain;

    NettyRequestDispatcher(ServletContext context, FilterChain filterChain) {
        this.context = context;
        this.filterChain = filterChain;
    }

    @Override
    public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        request.setAttribute(NettyHttpServletRequest.DISPATCHER_TYPE, DispatcherType.FORWARD);
        // TODO implement
    }

    @Override
    public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        request.setAttribute(NettyHttpServletRequest.DISPATCHER_TYPE, DispatcherType.INCLUDE);
        // TODO implement
    }

    void dispatch(ServletRequest request, ServletResponse response) throws ServletException, IOException {
        request.setAttribute(NettyHttpServletRequest.DISPATCHER_TYPE, DispatcherType.ASYNC);
        filterChain.doFilter(request, response);
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyServletRegistration.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import javax.servlet.*;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;

/**
 * A {@link org.springframework.boot.context.embedded.netty.NettyEmbeddedContext} {@link javax.servlet.ServletRegistration}.
 *
 * @author Danny Thomas
 */
class NettyServletRegistration extends AbstractNettyRegistration implements ServletRegistration.Dynamic {
    private volatile boolean initialised;
    private Servlet servlet;

    NettyServletRegistration(NettyEmbeddedContext context, String servletName, String className, Servlet servlet) {
        super(servletName, className, context);
        this.servlet = servlet;
    }

    public Servlet getServlet() throws ServletException {
        if (!initialised) {
            synchronized (this) {
                if (!initialised) {
                    if (null == servlet) {
                        try {
                            servlet = (Servlet) Class.forName(getClassName()).newInstance();
                        } catch (Exception e) {
                            throw new ServletException(e);
                        }
                    }
                    servlet.init(this);
                    initialised = true;
                }
            }
        }
        return servlet;
    }

    @Override
    public void setLoadOnStartup(int loadOnStartup) {

    }

    @Override
    public Set<String> setServletSecurity(ServletSecurityElement constraint) {
        return null;
    }

    @Override
    public void setMultipartConfig(MultipartConfigElement multipartConfig) {

    }

    @Override
    public void setRunAsRole(String roleName) {

    }

    @Override
    public Set<String> addMapping(String... urlPatterns) {
        // TODO check for conflicts

        NettyEmbeddedContext context = getNettyContext();
        for (String urlPattern : urlPatterns) {
            context.addServletMapping(urlPattern, getName());
        }
        return Collections.emptySet();
    }

    @Override
    public Collection<String> getMappings() {
        return null;
    }

    @Override
    public String getRunAsRole() {
        return null;
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/RequestDispatcherHandler.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * A {@link io.netty.channel.ChannelInboundHandler} that bridges to and from {@link HttpServletRequest}s and
 * {@link HttpServletResponse}s from Netty HTTP codec objects.
 *
 * @author Danny Thomas
 */
@ChannelHandler.Sharable
class RequestDispatcherHandler extends SimpleChannelInboundHandler<NettyHttpServletRequest> {
    private final Log logger = LogFactory.getLog(getClass());
    private final NettyEmbeddedContext context;

    RequestDispatcherHandler(NettyEmbeddedContext context) {
        this.context = checkNotNull(context);
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        ctx.flush();
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, NettyHttpServletRequest request) throws Exception {
        HttpServletResponse servletResponse = (HttpServletResponse) request.getServletResponse();
        try {
            NettyRequestDispatcher dispatcher = (NettyRequestDispatcher) context.getRequestDispatcher(request.getRequestURI());
            if (dispatcher == null) {
                servletResponse.sendError(404);
                return;
            }
            dispatcher.dispatch(request, servletResponse);
        } finally {
            if (!request.isAsyncStarted()) {
                servletResponse.getOutputStream().close();
            }
        }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error("Unexpected exception caught during request", cause);
        ctx.close();
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/ServletContentHandler.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.*;

/**
 * {@link io.netty.channel.ChannelInboundHandler} responsible for initial request handling, and getting received
 * {@link HttpContent} messages to the {@link HttpContentInputStream} for the request.
 */
class ServletContentHandler extends ChannelInboundHandlerAdapter {
    private final NettyEmbeddedContext servletContext;
    private HttpContentInputStream inputStream; // FIXME this feels wonky, need a better approach

    ServletContentHandler(NettyEmbeddedContext servletContext) {
        this.servletContext = servletContext;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        inputStream = new HttpContentInputStream(ctx.channel());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        if (msg instanceof HttpRequest) {
            HttpRequest request = (HttpRequest) msg;
            HttpResponse response = new DefaultHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, false);
            HttpHeaders.setKeepAlive(response, HttpHeaders.isKeepAlive(request));
            NettyHttpServletResponse servletResponse = new NettyHttpServletResponse(ctx, servletContext, response);
            NettyHttpServletRequest servletRequest = new NettyHttpServletRequest(ctx, servletContext, request, servletResponse, inputStream);
            if (HttpHeaders.is100ContinueExpected(request)) {
                ctx.write(new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.CONTINUE), ctx.voidPromise());
            }
            ctx.fireChannelRead(servletRequest);
        }
        if (msg instanceof HttpContent) {
            inputStream.addContent((HttpContent) msg);
        }
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        inputStream.close();
    }
}

================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/SimpleFilterChain.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty;

import javax.servlet.*;
import java.io.IOException;
import java.util.Iterator;

import static com.google.common.base.Preconditions.checkNotNull;

/**
 * A very simple {@link FilterChain} implementation.
 *
 * @author Danny Thomas
 */
class SimpleFilterChain implements FilterChain {
    private final Iterator<Filter> filterIterator;
    private final Servlet servlet;

    SimpleFilterChain(Servlet servlet, Iterable<Filter> filters) throws ServletException {
        this.filterIterator = checkNotNull(filters).iterator();
        this.servlet = checkNotNull(servlet);
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response) throws IOException, ServletException {
        if (filterIterator.hasNext()) {
            Filter filter = filterIterator.next();
            filter.doFilter(request, response, this);
        } else {
            servlet.service(request, response);
        }
    }
}


================================================
FILE: src/main/java/org/springframework/boot/context/embedded/netty/package-info.java
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

/**
 * Comment here.
 */
package org.springframework.boot.context.embedded.netty;

================================================
FILE: src/test/groovy/org/springframework/boot/context/embedded/netty/HttpContentInputStreamTest.groovy
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty

import com.google.common.base.Charsets
import io.netty.buffer.Unpooled
import io.netty.channel.Channel
import io.netty.handler.codec.http.DefaultHttpContent
import io.netty.handler.codec.http.LastHttpContent
import spock.lang.Specification

/**
 * Tests for {@link HttpContentInputStream}.
 */
class HttpContentInputStreamTest extends Specification {
    def channel
    def stream

    def setup() {
        channel = Mock(Channel)
        stream = new HttpContentInputStream(channel)
    }

    def 'a read with a an empty last content returns -1'() {
        given:
        stream.addContent(LastHttpContent.EMPTY_LAST_CONTENT)

        expect:
        stream.read() == -1
    }

    def 'a read with an empty last content, for a non-active channel, returns -1'() {
        given:
        stream.addContent(LastHttpContent.EMPTY_LAST_CONTENT)

        expect:
        stream.read() == -1
    }

    def 'an attempt to read with a non-active channel, throws IOException'() {
        given:
        channel.isActive() >> false

        when:
        stream.read()

        then:
        thrown(IOException)
    }

    def 'expected number of bytes and content is read for a single content read'() {
        when:
        stream.addContent(new DefaultHttpContent(Unpooled.copiedBuffer("My hovercraft is full of eels.", Charsets.UTF_8)))

        then:
        def b = new byte[30]
        stream.read(b, 0, 30) == 30
        new String(b) == "My hovercraft is full of eels."
    }

    def 'the expected number of bytes and content is read for partial read of two component contents'() {
        when:
        stream.addContent(new DefaultHttpContent(Unpooled.copiedBuffer("My hovercraft is full of eels.", Charsets.UTF_8)))
        stream.addContent(new DefaultHttpContent(Unpooled.copiedBuffer(" I will not buy this record, it is scratched.", Charsets.UTF_8)))

        then:
        def b = new byte[75]
        stream.read(b, 0, 30) == 30
        stream.read(b, 30, 45) == 45
        new String(b) == "My hovercraft is full of eels. I will not buy this record, it is scratched."
    }

    def 'zero length read returns 0'() {
        expect:
        stream.read(new byte[0], 0, 0) == 0
    }

    def 'stream is not finished'() {
        expect:
        !stream.isFinished()
    }

    def 'stream is not ready'() {
        expect:
        !stream.isReady()
    }

    def 'stream has no available bytes'() {
        expect:
        stream.available() == 0
    }
}


================================================
FILE: src/test/groovy/org/springframework/boot/context/embedded/netty/PackageSanityTest.groovy
================================================
/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package org.springframework.boot.context.embedded.netty

import com.google.common.base.Predicate
import com.google.common.testing.AbstractPackageSanityTests
import io.netty.buffer.ByteBuf
import io.netty.buffer.Unpooled
import org.junit.Ignore

import javax.annotation.Nullable

/**
 * Sanity tests for {@link org.springframework.boot.context.embedded.netty}.
 */
@Ignore
// FIXME I've added a bunch of new classes that can't be instantiated automatically, that'll I'll need to add back here
class PackageSanityTest extends AbstractPackageSanityTests {
    PackageSanityTest() {
        setDefault(ByteBuf, Unpooled.buffer())
        setDefault(NettyEmbeddedContext, new NettyEmbeddedContext("/", Thread.currentThread().getContextClassLoader(), "ServerInfo"))
        ignoreClasses(new Predicate<Class<?>>() {
            @Override
            boolean apply(@Nullable Class<?> input) {
                input == AbstractNettyRegistration
            }
        })
    }
}
Download .txt
gitextract_f34d6oz9/

├── .gitignore
├── .travis.yml
├── LICENSE.txt
├── NOTICE.txt
├── README.md
├── build.gradle
├── gradle/
│   ├── benchmark.gradle
│   ├── dependencies.gradle
│   ├── idea-codestyle.xml
│   ├── idea-copyright.xml
│   ├── idea-entrypoints.xml
│   ├── idea-inspections.xml
│   ├── idea.gradle
│   ├── integTest.gradle
│   ├── maven.gradle
│   ├── test.gradle
│   └── wrapper/
│       ├── gradle-wrapper.jar
│       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src/
    ├── integTest/
    │   ├── groovy/
    │   │   └── org/
    │   │       └── springframework/
    │   │           └── boot/
    │   │               └── context/
    │   │                   └── embedded/
    │   │                       └── netty/
    │   │                           └── NettyEmbeddedServletContainerAutoConfigurationIntegrationTest.groovy
    │   ├── java/
    │   │   └── org/
    │   │       └── springframework/
    │   │           └── boot/
    │   │               └── context/
    │   │                   └── embedded/
    │   │                       └── netty/
    │   │                           ├── HttpContentInputStreamBenchmark.java
    │   │                           ├── HttpResponseOutputStreamBenchmark.java
    │   │                           ├── NettyHttpServletResponseBenchmark.java
    │   │                           ├── StubChannelHandlerContext.java
    │   │                           └── TestApplication.java
    │   └── resources/
    │       └── logback.xml
    ├── main/
    │   └── java/
    │       └── org/
    │           └── springframework/
    │               └── boot/
    │                   └── context/
    │                       └── embedded/
    │                           └── netty/
    │                               ├── AbstractNettyRegistration.java
    │                               ├── HttpContentInputStream.java
    │                               ├── HttpResponseOutputStream.java
    │                               ├── NettyAsyncContext.java
    │                               ├── NettyEmbeddedContext.java
    │                               ├── NettyEmbeddedServletContainer.java
    │                               ├── NettyEmbeddedServletContainerAutoConfiguration.java
    │                               ├── NettyEmbeddedServletContainerFactory.java
    │                               ├── NettyEmbeddedServletInitializer.java
    │                               ├── NettyFilterRegistration.java
    │                               ├── NettyHttpServletRequest.java
    │                               ├── NettyHttpServletResponse.java
    │                               ├── NettyRequestDispatcher.java
    │                               ├── NettyServletRegistration.java
    │                               ├── RequestDispatcherHandler.java
    │                               ├── ServletContentHandler.java
    │                               ├── SimpleFilterChain.java
    │                               └── package-info.java
    └── test/
        └── groovy/
            └── org/
                └── springframework/
                    └── boot/
                        └── context/
                            └── embedded/
                                └── netty/
                                    ├── HttpContentInputStreamTest.groovy
                                    └── PackageSanityTest.groovy
Download .txt
SYMBOL INDEX (366 symbols across 22 files)

FILE: src/integTest/java/org/springframework/boot/context/embedded/netty/HttpContentInputStreamBenchmark.java
  class HttpContentInputStreamBenchmark (line 35) | @State(Scope.Group)
    method setup (line 44) | @Setup
    method addContent (line 50) | @Benchmark
    method read (line 56) | @Benchmark
    method main (line 62) | public static void main(String[] args) throws RunnerException {

FILE: src/integTest/java/org/springframework/boot/context/embedded/netty/HttpResponseOutputStreamBenchmark.java
  class HttpResponseOutputStreamBenchmark (line 37) | @State(Scope.Benchmark)
    method setup (line 47) | @Setup
    method writeByte (line 57) | @Benchmark
    method writeBytes (line 64) | @Benchmark
    method main (line 69) | public static void main(String[] args) throws RunnerException {

FILE: src/integTest/java/org/springframework/boot/context/embedded/netty/NettyHttpServletResponseBenchmark.java
  class NettyHttpServletResponseBenchmark (line 32) | @State(Scope.Benchmark)
    method setup (line 38) | @Setup
    method setContentType (line 46) | @Benchmark
    method setContentTypeHeader (line 51) | @Benchmark
    method getFormattedDate (line 56) | @Benchmark
    method main (line 61) | public static void main(String[] args) throws RunnerException {

FILE: src/integTest/java/org/springframework/boot/context/embedded/netty/StubChannelHandlerContext.java
  class StubChannelHandlerContext (line 33) | public class StubChannelHandlerContext implements ChannelHandlerContext {
    method alloc (line 36) | @Override
    method write (line 41) | @Override
    method write (line 47) | @Override
    method channel (line 57) | @Override
    method executor (line 62) | @Override
    method name (line 67) | @Override
    method handler (line 72) | @Override
    method isRemoved (line 77) | @Override
    method fireChannelRegistered (line 82) | @Override
    method fireChannelUnregistered (line 87) | @Override
    method fireChannelActive (line 92) | @Override
    method fireChannelInactive (line 97) | @Override
    method fireExceptionCaught (line 102) | @Override
    method fireUserEventTriggered (line 107) | @Override
    method fireChannelRead (line 112) | @Override
    method fireChannelReadComplete (line 117) | @Override
    method fireChannelWritabilityChanged (line 122) | @Override
    method bind (line 127) | @Override
    method connect (line 132) | @Override
    method connect (line 137) | @Override
    method disconnect (line 142) | @Override
    method close (line 147) | @Override
    method deregister (line 152) | @Override
    method bind (line 157) | @Override
    method connect (line 162) | @Override
    method connect (line 167) | @Override
    method disconnect (line 172) | @Override
    method close (line 177) | @Override
    method deregister (line 182) | @Override
    method read (line 187) | @Override
    method flush (line 192) | @Override
    method writeAndFlush (line 197) | @Override
    method writeAndFlush (line 202) | @Override
    method pipeline (line 207) | @Override
    method newPromise (line 212) | @Override
    method newProgressivePromise (line 217) | @Override
    method newSucceededFuture (line 222) | @Override
    method newFailedFuture (line 227) | @Override
    method voidPromise (line 232) | @Override
    method attr (line 237) | @Override
    method hasAttr (line 242) | @Override

FILE: src/integTest/java/org/springframework/boot/context/embedded/netty/TestApplication.java
  class TestApplication (line 45) | @Controller
    method call (line 52) | @Override
    method plaintext (line 58) | @RequestMapping(value = "/plaintext", produces = "text/plain")
    method async (line 64) | @RequestMapping(value = "/async", produces = "text/plain")
    method json (line 70) | @RequestMapping(value = "/json", produces = "application/json")
    method upload (line 76) | @RequestMapping(value = "/upload", method = RequestMethod.POST)
    method sleepy (line 92) | @RequestMapping("/sleepy")
    method nullServletRegistration (line 100) | @Bean
    method main (line 105) | public static void main(String[] args) {
    class Message (line 109) | private static class Message {
      method Message (line 112) | public Message(String message) {
      method getMessage (line 116) | public String getMessage() {
    class NullHttpServlet (line 121) | private class NullHttpServlet extends HttpServlet {
      method doGet (line 122) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/AbstractNettyRegistration.java
  class AbstractNettyRegistration (line 38) | class AbstractNettyRegistration implements Registration, Registration.Dy...
    method AbstractNettyRegistration (line 44) | protected AbstractNettyRegistration(String name, String className, Net...
    method setAsyncSupported (line 50) | @Override
    method getName (line 55) | @Override
    method getClassName (line 60) | @Override
    method setInitParameter (line 65) | @Override
    method getFilterName (line 72) | @Override
    method getServletName (line 77) | @Override
    method getServletContext (line 82) | @Override
    method getNettyContext (line 87) | protected NettyEmbeddedContext getNettyContext() {
    method getInitParameter (line 91) | @Override
    method getInitParameterNames (line 96) | @Override
    method setInitParameters (line 101) | @Override
    method getInitParameters (line 106) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/HttpContentInputStream.java
  class HttpContentInputStream (line 43) | class HttpContentInputStream extends ServletInputStream {
    method HttpContentInputStream (line 50) | HttpContentInputStream(Channel channel) {
    method addContent (line 56) | public void addContent(HttpContent httpContent) {
    method readLine (line 62) | @Override
    method isFinished (line 69) | @Override
    method isLastContent (line 75) | private boolean isLastContent() {
    method isReady (line 79) | @Override
    method setReadListener (line 85) | @Override
    method skip (line 92) | @Override
    method available (line 99) | @Override
    method close (line 104) | @Override
    method read (line 113) | @Override
    method read (line 129) | @Override
    method readContent (line 138) | private ByteBuf readContent(int length) throws IOException {
    method poll (line 147) | private void poll() throws IOException {
    method checkNotClosed (line 167) | private void checkNotClosed() {

FILE: src/main/java/org/springframework/boot/context/embedded/netty/HttpResponseOutputStream.java
  class HttpResponseOutputStream (line 42) | class HttpResponseOutputStream extends ServletOutputStream {
    method HttpResponseOutputStream (line 52) | HttpResponseOutputStream(ChannelHandlerContext ctx, NettyHttpServletRe...
    method isReady (line 58) | @Override
    method setWriteListener (line 63) | @Override
    method write (line 70) | @Override
    method write (line 84) | @Override
    method writeBufferIfNeeded (line 90) | private void writeBufferIfNeeded(int len) throws IOException {
    method flush (line 96) | @Override
    method flushBuffer (line 101) | private void flushBuffer() {
    method flushBuffer (line 105) | private void flushBuffer(boolean lastContent) {
    method writeContent (line 116) | private void writeContent(ByteBuf content, boolean lastContent) {
    method writeResponse (line 134) | private void writeResponse(boolean lastContent) {
    method close (line 147) | @Override
    method resetBuffer (line 161) | void resetBuffer() {
    method getBufferSize (line 166) | int getBufferSize() {
    method setBufferSize (line 170) | void setBufferSize(int size) {

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyAsyncContext.java
  class NettyAsyncContext (line 34) | class NettyAsyncContext implements AsyncContext {
    method NettyAsyncContext (line 41) | NettyAsyncContext(ServletRequest servletRequest, ChannelHandlerContext...
    method startAsync (line 47) | AsyncContext startAsync(ServletRequest servletRequest, ServletResponse...
    method getRequest (line 54) | @Override
    method getResponse (line 59) | @Override
    method hasOriginalRequestAndResponse (line 64) | @Override
    method dispatch (line 69) | @Override
    method dispatch (line 82) | @Override
    method dispatch (line 87) | @Override
    method complete (line 113) | @Override
    method start (line 123) | @Override
    method addListener (line 128) | @Override
    method addListener (line 133) | @Override
    method createListener (line 138) | @Override
    method setTimeout (line 143) | @Override
    method getTimeout (line 148) | @Override
    method isAsyncStarted (line 153) | public boolean isAsyncStarted() {

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedContext.java
  class NettyEmbeddedContext (line 38) | class NettyEmbeddedContext implements ServletContext {
    method NettyEmbeddedContext (line 49) | NettyEmbeddedContext(String contextPath, ClassLoader classLoader, Stri...
    method setInitialised (line 55) | public void setInitialised(boolean initialised) {
    method isInitialised (line 59) | public boolean isInitialised() {
    method checkNotInitialised (line 63) | public void checkNotInitialised() {
    method addServletMapping (line 67) | public void addServletMapping(String urlPattern, String name) {
    method addFilterMapping (line 72) | public void addFilterMapping(EnumSet<DispatcherType> dispatcherTypes, ...
    method getContext (line 77) | @Override
    method getContextPath (line 82) | @Override
    method getMajorVersion (line 87) | @Override
    method getMinorVersion (line 92) | @Override
    method getEffectiveMajorVersion (line 97) | @Override
    method getEffectiveMinorVersion (line 102) | @Override
    method getMimeType (line 107) | @Override
    method getResourcePaths (line 112) | @Override
    method getResource (line 117) | @Override
    method getResourceAsStream (line 122) | @Override
    method getRequestDispatcher (line 127) | @Override
    method getNamedDispatcher (line 153) | @Override
    method getServlet (line 158) | @Override
    method getServlets (line 163) | @Override
    method getServletNames (line 168) | @Override
    method log (line 173) | @Override
    method log (line 178) | @Override
    method log (line 183) | @Override
    method getRealPath (line 188) | @Override
    method getServerInfo (line 193) | @Override
    method getServerInfoAscii (line 198) | AsciiString getServerInfoAscii() {
    method getInitParameter (line 202) | @Override
    method getInitParameterNames (line 207) | @Override
    method setInitParameter (line 212) | @Override
    method getAttribute (line 217) | @Override
    method getAttributeNames (line 222) | @Override
    method setAttribute (line 227) | @Override
    method removeAttribute (line 232) | @Override
    method getServletContextName (line 237) | @Override
    method addServlet (line 242) | @Override
    method addServlet (line 247) | @Override
    method addServlet (line 252) | @Override
    method addServlet (line 257) | private ServletRegistration.Dynamic addServlet(String servletName, Str...
    method createServlet (line 263) | @Override
    method getServletRegistration (line 268) | @Override
    method getServletRegistrations (line 273) | @Override
    method addFilter (line 278) | @Override
    method addFilter (line 283) | @Override
    method addFilter (line 288) | private javax.servlet.FilterRegistration.Dynamic addFilter(String filt...
    method addFilter (line 295) | @Override
    method createFilter (line 300) | @Override
    method getFilterRegistration (line 305) | @Override
    method getFilterRegistrations (line 310) | @Override
    method getSessionCookieConfig (line 315) | @Override
    method setSessionTrackingModes (line 320) | @Override
    method getDefaultSessionTrackingModes (line 325) | @Override
    method getEffectiveSessionTrackingModes (line 330) | @Override
    method addListener (line 335) | @Override
    method addListener (line 340) | @Override
    method addListener (line 345) | @Override
    method createListener (line 350) | @Override
    method declareRoles (line 355) | @Override
    method getVirtualServerName (line 360) | @Override
    method getClassLoader (line 365) | @Override
    method getJspConfigDescriptor (line 370) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainer.java
  class NettyEmbeddedServletContainer (line 51) | public class NettyEmbeddedServletContainer implements EmbeddedServletCon...
    method NettyEmbeddedServletContainer (line 60) | public NettyEmbeddedServletContainer(InetSocketAddress address, NettyE...
    method start (line 65) | @Override
    method groups (line 84) | private void groups(ServerBootstrap b) {
    method stop (line 103) | @Override
    method getPort (line 120) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainerAutoConfiguration.java
  class NettyEmbeddedServletContainerAutoConfiguration (line 38) | @Order(Ordered.HIGHEST_PRECEDENCE)
    class EmbeddedNetty (line 43) | @Configuration
      method nettyEmbeddedServletContainerFactory (line 47) | @Bean

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainerFactory.java
  class NettyEmbeddedServletContainerFactory (line 40) | public class NettyEmbeddedServletContainerFactory extends AbstractEmbedd...
    method getEmbeddedServletContainer (line 44) | @Override
    method setResourceLoader (line 71) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletInitializer.java
  class NettyEmbeddedServletInitializer (line 33) | class NettyEmbeddedServletInitializer extends ChannelInitializer<SocketC...
    method NettyEmbeddedServletInitializer (line 38) | NettyEmbeddedServletInitializer(EventExecutorGroup servletExecutor, Ne...
    method initChannel (line 44) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyFilterRegistration.java
  class NettyFilterRegistration (line 32) | class NettyFilterRegistration extends AbstractNettyRegistration implemen...
    method NettyFilterRegistration (line 36) | NettyFilterRegistration(NettyEmbeddedContext context, String filterNam...
    method getFilter (line 41) | public Filter getFilter() throws ServletException {
    method addMappingForServletNames (line 60) | @Override
    method getServletNameMappings (line 65) | @Override
    method addMappingForUrlPatterns (line 70) | @Override
    method getUrlPatternMappings (line 78) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyHttpServletRequest.java
  class NettyHttpServletRequest (line 36) | class NettyHttpServletRequest implements HttpServletRequest {
    method NettyHttpServletRequest (line 49) | NettyHttpServletRequest(ChannelHandlerContext ctx, NettyEmbeddedContex...
    method getNettyRequest (line 58) | HttpRequest getNettyRequest() {
    method getAuthType (line 62) | @Override
    method getCookies (line 67) | @Override
    method getDateHeader (line 72) | @Override
    method getHeader (line 77) | @Override
    method getHeaders (line 82) | @Override
    method getHeaderNames (line 87) | @Override
    method getIntHeader (line 92) | @Override
    method getMethod (line 97) | @Override
    method getPathInfo (line 102) | @Override
    method getPathTranslated (line 107) | @Override
    method getContextPath (line 112) | @Override
    method getQueryString (line 119) | @Override
    method getRemoteUser (line 124) | @Override
    method isUserInRole (line 129) | @Override
    method getUserPrincipal (line 134) | @Override
    method getRequestedSessionId (line 139) | @Override
    method getRequestURI (line 144) | @Override
    method getRequestURL (line 149) | @Override
    method getServletPath (line 154) | @Override
    method getSession (line 159) | @Override
    method getSession (line 164) | @Override
    method changeSessionId (line 169) | @Override
    method isRequestedSessionIdValid (line 174) | @Override
    method isRequestedSessionIdFromCookie (line 179) | @Override
    method isRequestedSessionIdFromURL (line 184) | @Override
    method isRequestedSessionIdFromUrl (line 189) | @Override
    method authenticate (line 194) | @Override
    method login (line 199) | @Override
    method logout (line 204) | @Override
    method getParts (line 209) | @Override
    method getPart (line 214) | @Override
    method upgrade (line 219) | @Override
    method getAttribute (line 224) | @Override
    method getAttributeNames (line 231) | @Override
    method getCharacterEncoding (line 238) | @Override
    method setCharacterEncoding (line 243) | @Override
    method getContentLength (line 248) | @Override
    method getContentLengthLong (line 253) | @Override
    method getContentType (line 258) | @Override
    method getInputStream (line 263) | @Override
    method getParameter (line 268) | @Override
    method getParameterNames (line 273) | @Override
    method getParameterValues (line 278) | @Override
    method getParameterMap (line 283) | @Override
    method getProtocol (line 288) | @Override
    method getScheme (line 293) | @Override
    method getServerName (line 298) | @Override
    method getServerPort (line 303) | @Override
    method getReader (line 308) | @Override
    method getRemoteAddr (line 313) | @Override
    method getRemoteHost (line 318) | @Override
    method setAttribute (line 323) | @Override
    method removeAttribute (line 330) | @Override
    method getLocale (line 337) | @Override
    method getLocales (line 342) | @Override
    method isSecure (line 347) | @Override
    method getRequestDispatcher (line 352) | @Override
    method getRealPath (line 357) | @Override
    method getRemotePort (line 362) | @Override
    method getLocalName (line 367) | @Override
    method getLocalAddr (line 372) | @Override
    method getLocalPort (line 377) | @Override
    method getServletContext (line 382) | @Override
    method startAsync (line 387) | @Override
    method startAsync (line 392) | @Override
    method isAsyncStarted (line 397) | @Override
    method setAsyncSupported (line 402) | void setAsyncSupported(boolean asyncSupported) {
    method isAsyncSupported (line 406) | @Override
    method getAsyncContext (line 411) | @Override
    method getDispatcherType (line 419) | @Override
    method getServletResponse (line 424) | public ServletResponse getServletResponse() {

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyHttpServletResponse.java
  class NettyHttpServletResponse (line 47) | class NettyHttpServletResponse implements HttpServletResponse {
    method initialValue (line 49) | @Override
    method NettyHttpServletResponse (line 69) | NettyHttpServletResponse(ChannelHandlerContext ctx, NettyEmbeddedConte...
    method getNettyResponse (line 79) | public HttpResponse getNettyResponse() {
    method getFormattedDate (line 96) | @VisibleForTesting
    method addCookie (line 101) | @Override
    method containsHeader (line 106) | @Override
    method encodeURL (line 111) | @Override
    method encodeRedirectURL (line 116) | @Override
    method encodeUrl (line 121) | @Override
    method encodeRedirectUrl (line 126) | @Override
    method sendError (line 131) | @Override
    method sendError (line 137) | @Override
    method sendRedirect (line 143) | @Override
    method setDateHeader (line 149) | @Override
    method addDateHeader (line 154) | @Override
    method setHeader (line 159) | @Override
    method setHeaderField (line 167) | private boolean setHeaderField(String name, String value) {
    method addHeader (line 180) | @Override
    method setIntHeader (line 188) | @Override
    method addIntHeader (line 193) | @Override
    method setStatus (line 198) | @Override
    method setStatus (line 203) | @Override
    method getStatus (line 208) | @Override
    method getHeader (line 213) | @Override
    method getHeaders (line 218) | @Override
    method getHeaderNames (line 223) | @Override
    method getCharacterEncoding (line 228) | @Override
    method getContentType (line 233) | @Override
    method getOutputStream (line 238) | @Override
    method getWriter (line 245) | @Override
    method setCharacterEncoding (line 254) | @Override
    method setContentType (line 262) | @Override
    method hasWriter (line 282) | private boolean hasWriter() {
    method setContentLength (line 286) | @Override
    method setContentLengthLong (line 291) | @Override
    method setBufferSize (line 296) | @Override
    method getBufferSize (line 302) | @Override
    method flushBuffer (line 307) | @Override
    method resetBuffer (line 313) | @Override
    method isCommitted (line 319) | @Override
    method checkNotCommitted (line 324) | void checkNotCommitted() {
    method reset (line 328) | @Override
    method setLocale (line 335) | @Override
    method getLocale (line 340) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyRequestDispatcher.java
  class NettyRequestDispatcher (line 26) | class NettyRequestDispatcher implements RequestDispatcher {
    method NettyRequestDispatcher (line 30) | NettyRequestDispatcher(ServletContext context, FilterChain filterChain) {
    method forward (line 35) | @Override
    method include (line 41) | @Override
    method dispatch (line 47) | void dispatch(ServletRequest request, ServletResponse response) throws...

FILE: src/main/java/org/springframework/boot/context/embedded/netty/NettyServletRegistration.java
  class NettyServletRegistration (line 30) | class NettyServletRegistration extends AbstractNettyRegistration impleme...
    method NettyServletRegistration (line 34) | NettyServletRegistration(NettyEmbeddedContext context, String servletN...
    method getServlet (line 39) | public Servlet getServlet() throws ServletException {
    method setLoadOnStartup (line 58) | @Override
    method setServletSecurity (line 63) | @Override
    method setMultipartConfig (line 68) | @Override
    method setRunAsRole (line 73) | @Override
    method addMapping (line 78) | @Override
    method getMappings (line 89) | @Override
    method getRunAsRole (line 94) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/RequestDispatcherHandler.java
  class RequestDispatcherHandler (line 37) | @ChannelHandler.Sharable
    method RequestDispatcherHandler (line 42) | RequestDispatcherHandler(NettyEmbeddedContext context) {
    method channelReadComplete (line 46) | @Override
    method channelRead0 (line 51) | @Override
    method exceptionCaught (line 68) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/ServletContentHandler.java
  class ServletContentHandler (line 28) | class ServletContentHandler extends ChannelInboundHandlerAdapter {
    method ServletContentHandler (line 32) | ServletContentHandler(NettyEmbeddedContext servletContext) {
    method channelActive (line 36) | @Override
    method channelRead (line 41) | @Override
    method channelInactive (line 59) | @Override

FILE: src/main/java/org/springframework/boot/context/embedded/netty/SimpleFilterChain.java
  class SimpleFilterChain (line 31) | class SimpleFilterChain implements FilterChain {
    method SimpleFilterChain (line 35) | SimpleFilterChain(Servlet servlet, Iterable<Filter> filters) throws Se...
    method doFilter (line 40) | @Override
Condensed preview — 48 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (156K chars).
[
  {
    "path": ".gitignore",
    "chars": 171,
    "preview": "### Gradle ###\n.gradle\nbuild/\n\n### Intellij ###\n\n## Directory-based project format\n.idea/\n\n## File-based project format\n"
  },
  {
    "path": ".travis.yml",
    "chars": 15,
    "preview": "language: java\n"
  },
  {
    "path": "LICENSE.txt",
    "chars": 11358,
    "preview": "\n                                 Apache License\n                           Version 2.0, January 2004\n                  "
  },
  {
    "path": "NOTICE.txt",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "README.md",
    "chars": 3680,
    "preview": "A prototype Netty embedded servlet bridge for Spring Boot.\n\nIncludes basic filter and servlet support. I'm fairly new to"
  },
  {
    "path": "build.gradle",
    "chars": 1305,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "gradle/benchmark.gradle",
    "chars": 946,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "gradle/dependencies.gradle",
    "chars": 2218,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "gradle/idea-codestyle.xml",
    "chars": 7181,
    "preview": "<!--\n  ~ Copyright 2014 the original author or authors.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "gradle/idea-copyright.xml",
    "chars": 1724,
    "preview": "<!--\n  ~ Copyright 2014 the original author or authors.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "gradle/idea-entrypoints.xml",
    "chars": 511,
    "preview": "<component name=\"EntryPointsManager\">\n  <entry_points version=\"2.0\"/>\n  <list size=\"4\">\n    <item index=\"0\" class=\"java."
  },
  {
    "path": "gradle/idea-inspections.xml",
    "chars": 1595,
    "preview": "<!--\n  ~ Copyright 2014 the original author or authors.\n  ~\n  ~ Licensed under the Apache License, Version 2.0 (the \"Lic"
  },
  {
    "path": "gradle/idea.gradle",
    "chars": 2554,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "gradle/integTest.gradle",
    "chars": 1925,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "gradle/maven.gradle",
    "chars": 676,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "gradle/test.gradle",
    "chars": 1720,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "chars": 230,
    "preview": "#Mon Nov 24 15:05:30 GMT 2014\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "gradlew",
    "chars": 5080,
    "preview": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start "
  },
  {
    "path": "gradlew.bat",
    "chars": 2404,
    "preview": "@if \"%DEBUG%\" == \"\" @echo off\r\n@rem ##########################################################################\r\n@rem\r\n@r"
  },
  {
    "path": "settings.gradle",
    "chars": 1273,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/integTest/groovy/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainerAutoConfigurationIntegrationTest.groovy",
    "chars": 1321,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/integTest/java/org/springframework/boot/context/embedded/netty/HttpContentInputStreamBenchmark.java",
    "chars": 2151,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/integTest/java/org/springframework/boot/context/embedded/netty/HttpResponseOutputStreamBenchmark.java",
    "chars": 2777,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/integTest/java/org/springframework/boot/context/embedded/netty/NettyHttpServletResponseBenchmark.java",
    "chars": 2411,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/integTest/java/org/springframework/boot/context/embedded/netty/StubChannelHandlerContext.java",
    "chars": 5442,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/integTest/java/org/springframework/boot/context/embedded/netty/TestApplication.java",
    "chars": 4180,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/integTest/resources/logback.xml",
    "chars": 917,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!--\n  ~ Copyright 2014 the original author or authors.\n  ~\n  ~ Licensed under th"
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/AbstractNettyRegistration.java",
    "chars": 3060,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/HttpContentInputStream.java",
    "chars": 5345,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/HttpResponseOutputStream.java",
    "chars": 5436,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyAsyncContext.java",
    "chars": 4766,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedContext.java",
    "chars": 10194,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainer.java",
    "chars": 5066,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainerAutoConfiguration.java",
    "chars": 2303,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletContainerFactory.java",
    "chars": 3310,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyEmbeddedServletInitializer.java",
    "chars": 2063,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyFilterRegistration.java",
    "chars": 2727,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyHttpServletRequest.java",
    "chars": 9438,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyHttpServletResponse.java",
    "chars": 9477,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyRequestDispatcher.java",
    "chars": 1830,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/NettyServletRegistration.java",
    "chars": 2818,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/RequestDispatcherHandler.java",
    "chars": 2652,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/ServletContentHandler.java",
    "chars": 2675,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/SimpleFilterChain.java",
    "chars": 1609,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/main/java/org/springframework/boot/context/embedded/netty/package-info.java",
    "chars": 698,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/test/groovy/org/springframework/boot/context/embedded/netty/HttpContentInputStreamTest.groovy",
    "chars": 3144,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  },
  {
    "path": "src/test/groovy/org/springframework/boot/context/embedded/netty/PackageSanityTest.groovy",
    "chars": 1587,
    "preview": "/*\n * Copyright 2014 the original author or authors.\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\""
  }
]

// ... and 1 more files (download for full content)

About this extraction

This page contains the full source code of the DanielThomas/spring-boot-starter-netty GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 48 files (142.5 KB), approximately 33.3k tokens, and a symbol index with 366 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!