Merge branch 'jetty-9.4.x' of github.com:eclipse/jetty.project into jetty-9.4.x
This commit is contained in:
commit
1b3b57b2d3
11
VERSION.txt
11
VERSION.txt
|
@ -1,7 +1,9 @@
|
|||
jetty-9.4.0-SNAPSHOT
|
||||
|
||||
jetty-9.3.11.v20160721 - 21 July 2016
|
||||
+ 230 customize Content-Type in ErrorHandler's default error page
|
||||
+ 592 Support no-value Host header in HttpParser
|
||||
+ 631 SLOTH protection
|
||||
+ 643 NPE in passing websocket client test
|
||||
+ 649 LDAPLoginModule should disallow blank username and password
|
||||
+ 658 Add memcached option for gcloud-sessions in jetty-9.3
|
||||
|
@ -11,6 +13,7 @@ jetty-9.3.11.v20160721 - 21 July 2016
|
|||
outside of ${jetty.base}
|
||||
+ 668 Introduce optional `jetty.deploy.defaultsDescriptorPath` for
|
||||
jetty-deploy defaults descriptor outside of ${jetty.home}
|
||||
+ 669 Support UNC paths in PathResource
|
||||
+ 671 Incorrect ALPN default protocol
|
||||
+ 672 Allow logging configuration announcement to be programmatically disabled
|
||||
+ 673 ClasspathPattern needs a match all pattern
|
||||
|
@ -35,15 +38,18 @@ jetty-9.3.11.v20160721 - 21 July 2016
|
|||
+ 701 Document CachingWebAppClassLoader
|
||||
+ 706 org.apache.jasper.compiler.disablejsr199 is no longer present in Jetty
|
||||
9.3+
|
||||
+ 708 SslContextFactory: newSslServerSocket/newSslSocket are not completely
|
||||
customized
|
||||
+ 708 SslContextFactory: newSslServerSocket/newSslSocket customization
|
||||
+ 717 GzipHandler.minGzipSize still compresses small responses
|
||||
+ 718 Document HttpClient transports
|
||||
+ 720 asciiToLowerCase throws NullPointerException
|
||||
+ 721 HTTP Response header value encoding is invalid for RFC7230
|
||||
+ 723 Improve bad/missing mime.properties reporting
|
||||
+ 726 Http2 Client parse error
|
||||
+ 730 "Slow" client causes IllegalStateException
|
||||
+ 733 Allow setCharacterEncoding after getOutputStream
|
||||
+ 739 Illegal WindowUpdate frame with delta=0
|
||||
+ 742 Fixed link to webtide.com
|
||||
+ 745 Removed README.txt
|
||||
+ 747 Update documentation to reflect TLS and SSL support
|
||||
+ 751 Remove usages of ArrayQueue
|
||||
+ 752 Implement support for HTTP2 SETTINGS_MAX_HEADER_LIST_SIZE
|
||||
|
@ -61,6 +67,7 @@ jetty-9.2.18.v20160721 - 21 July 2016
|
|||
jetty-9.3.11.M0 - 22 June 2016
|
||||
+ 425 Incorrect @ServerEndpoint Encoder/Decoder lifecycle
|
||||
+ 624 AsyncContext.onCompleted called twice
|
||||
+ 645 jetty-requestlog.xml default log path
|
||||
+ 654 Jetty 9.3 ServletContext.getResourceAsStream("/") returns an unusable
|
||||
stream
|
||||
+ 659 CONNECT request fails spuriously
|
||||
|
|
|
@ -15,6 +15,13 @@
|
|||
<bundle-symbolic-name>${project.groupId}.embedded</bundle-symbolic-name>
|
||||
</properties>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.google.guava</groupId>
|
||||
<artifactId>guava</artifactId>
|
||||
<version>18.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util-ajax</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
# <username>: <password>[,<rolename> ...]
|
||||
#
|
||||
# Passwords may be clear text, obfuscated or checksummed. The class
|
||||
# org.eclipse.util.Password should be used to generate obfuscated
|
||||
# org.eclipse.jetty.util.security.Password should be used to generate obfuscated
|
||||
# passwords or password checksums
|
||||
#
|
||||
# If DIGEST Authentication is used, the password must be in a recoverable
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
[[jetty-jspc-maven-plugin]]
|
||||
=== Jetty Jspc Maven Plugin
|
||||
|
||||
This plugin will help you pre-compile your jsps and works in conjunction with the maven war plugin to put them inside an assembled war.
|
||||
This plugin will help you pre-compile your jsps and works in conjunction with the Maven war plugin to put them inside an assembled war.
|
||||
|
||||
[[jspc-config]]
|
||||
==== Configuration
|
||||
|
@ -26,7 +26,6 @@ Here's the basic setup required to put the jspc plugin into your build:
|
|||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jspc-maven-plugin</artifactId>
|
||||
|
@ -42,85 +41,82 @@ Here's the basic setup required to put the jspc plugin into your build:
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
|
||||
----
|
||||
|
||||
The configurable parameters are as follows:
|
||||
|
||||
webXmlFragment::
|
||||
Default value: $\{project.basedir}/target/webfrag.xml
|
||||
+
|
||||
File into which to generate the servlet declarations.
|
||||
Will be merged with an existing web.xml.
|
||||
Default value: `$\{project.basedir}/target/webfrag.xml`
|
||||
+
|
||||
File into which to generate the servlet declarations.
|
||||
Will be merged with an existing `web.xml`.
|
||||
webAppSourceDirectory::
|
||||
Default value: $\{project.basedir}/src/main/webapp
|
||||
+
|
||||
Root of resources directory where jsps, tags etc are located.
|
||||
Default value: `$\{project.basedir}/src/main/webapp`
|
||||
+
|
||||
Root of resources directory where jsps, tags etc are located.
|
||||
webXml::
|
||||
Default value: $\{project.basedir}/src/main/webapp/WEB-INF/web.xml
|
||||
+
|
||||
The web.xml file to use to merge with the generated fragments.
|
||||
Default value: `$\{project.basedir}/src/main/webapp/WEB-INF/web.xml`
|
||||
+
|
||||
The web.xml file to use to merge with the generated fragments.
|
||||
includes::
|
||||
Default value: **\/*.jsp, **\/*.jspx
|
||||
+
|
||||
The comma separated list of patterns for file extensions to be processed.
|
||||
Default value: `**\/*.jsp, **\/*.jspx`
|
||||
+
|
||||
The comma separated list of patterns for file extensions to be processed.
|
||||
excludes::
|
||||
Default value: **\/.svn\/**
|
||||
+
|
||||
The comma separated list of patterns for file extensions to be skipped.
|
||||
Default value: `**\/.svn\/**`
|
||||
+
|
||||
The comma separated list of patterns for file extensions to be skipped.
|
||||
classesDirectory::
|
||||
Default value: $\{project.build.outputDirectory}
|
||||
+
|
||||
Location of classes for the webapp.
|
||||
Default value: `$\{project.build.outputDirectory}`
|
||||
+
|
||||
Location of classes for the webapp.
|
||||
generatedClasses::
|
||||
Default value: $\{project.build.outputDirectory}
|
||||
+
|
||||
Location to put the generated classes for the jsps.
|
||||
Default value: `$\{project.build.outputDirectory}`
|
||||
+
|
||||
Location to put the generated classes for the jsps.
|
||||
insertionMarker::
|
||||
Default value: _none_
|
||||
+
|
||||
A marker string in the src web.xml file which indicates where to merge in the generated web.xml fragment.
|
||||
Note that the marker string will NOT be preserved during the insertion. Can be left blank, in which case the generated fragment is inserted just before the line containing </web-app>.
|
||||
Default value: _none_
|
||||
+
|
||||
A marker string in the src `web.xml` file which indicates where to merge in the generated web.xml fragment.
|
||||
Note that the marker string will NOT be preserved during the insertion.
|
||||
Can be left blank, in which case the generated fragment is inserted just before the line containing `</web-app>`.
|
||||
useProvidedScope::
|
||||
Default value: false
|
||||
+
|
||||
If true, jars of dependencies marked with <scope>provided</scope> will
|
||||
be placed on the compilation classpath.
|
||||
Default value: false
|
||||
+
|
||||
If true, jars of dependencies marked with <scope>provided</scope> will be placed on the compilation classpath.
|
||||
mergeFragment::
|
||||
Default value: true
|
||||
+
|
||||
Whether or not to merge the generated fragment file with the source web.xml.
|
||||
The merged file will go into the same directory as the webXmlFragment.
|
||||
Default value: true
|
||||
+
|
||||
Whether or not to merge the generated fragment file with the source web.xml.
|
||||
The merged file will go into the same directory as the webXmlFragment.
|
||||
keepSources::
|
||||
Default value: false
|
||||
+
|
||||
If true, the generated .java files are not deleted at the end of processing.
|
||||
Default value: false
|
||||
+
|
||||
If true, the generated .java files are not deleted at the end of processing.
|
||||
sourceVersion::
|
||||
Since jetty-9.3.6.
|
||||
Java version of jsp source files.
|
||||
Defaults to 1.7.
|
||||
Introduced in Jetty 9.3.6.
|
||||
Java version of jsp source files.
|
||||
Defaults to 1.7.
|
||||
targetVersion::
|
||||
Since jetty-9.3.6.
|
||||
Java version of class files generated from jsps.
|
||||
Defaults to 1.7.
|
||||
Introduced in Jetty 9.3.6.
|
||||
Java version of class files generated from jsps.
|
||||
Defaults to 1.7.
|
||||
tldJarNamePatterns::
|
||||
Default value: .*taglibs[^/]*\.jar|.*jstl-impl[^/]*\.jar$
|
||||
+
|
||||
Patterns of jars on the 'system' (ie container) path that contain tlds.
|
||||
Use | to separate each pattern.
|
||||
Default value: `.*taglibs[^/]*\.jar|.*jstl-impl[^/]*\.jar$`
|
||||
+
|
||||
Patterns of jars on the 'system' (ie container) path that contain tlds.
|
||||
Use | to separate each pattern.
|
||||
jspc::
|
||||
Default value: the org.apache.jasper.JspC instance being configured.
|
||||
+
|
||||
The JspC class actually performs the pre-compilation.
|
||||
All setters on the JspC class are available.
|
||||
You can http://central.maven.org/maven2/org/glassfish/web/javax.servlet.jsp/2.3.2/javax.servlet.jsp-2.3.2-javadoc.jar[download] the javadoc from http://central.maven.org/maven2/org/glassfish/web/javax.servlet.jsp/2.3.2/javax.servlet.jsp-2.3.2-javadoc.jar[here].
|
||||
Default value: the `org.apache.jasper.JspC` instance being configured.
|
||||
+
|
||||
The JspC class actually performs the pre-compilation.
|
||||
All setters on the JspC class are available.
|
||||
You can download the javadoc http://central.maven.org/maven2/org/glassfish/web/javax.servlet.jsp/2.3.2/javax.servlet.jsp-2.3.2-javadoc.jar[here].
|
||||
|
||||
Taking all the default settings, here's how to configure the war plugin to use the generated web.xml that includes all of the jsp servlet declarations:
|
||||
Taking all the default settings, here's how to configure the war plugin to use the generated `web.xml` that includes all of the jsp servlet declarations:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
|
@ -128,8 +124,6 @@ Taking all the default settings, here's how to configure the war plugin to use t
|
|||
<webXml>${project.basedir}/target/web.xml</webXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
|
||||
----
|
||||
|
||||
[[jspc-production-precompile]]
|
||||
|
@ -141,7 +135,6 @@ For example, the following profile will only be invoked if the flag `-Dprod` is
|
|||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>prod</id>
|
||||
|
@ -165,18 +158,13 @@ For example, the following profile will only be invoked if the flag `-Dprod` is
|
|||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
|
||||
----
|
||||
|
||||
So, the following invocation would cause your code to be compiled, the jsps to be compiled, the <servlet> and <servlet-mapping>s inserted in the web.xml and your webapp assembled into a war:
|
||||
The following invocation would cause your code to be compiled, the jsps to be compiled, the <servlet> and <servlet-mapping>s inserted in the `web.xml` and your webapp assembled into a war:
|
||||
|
||||
[source, screen, subs="{sub-order}"]
|
||||
....
|
||||
|
||||
$ mvn -Dprod package
|
||||
|
||||
|
||||
....
|
||||
|
||||
[[jspc-overlay-precompile]]
|
||||
|
@ -186,14 +174,13 @@ Precompiling jsps with an overlaid war requires a bit more configuration.
|
|||
This is because you need to separate the steps of unpacking the overlaid war and then repacking the final target war so the jetty-jspc-maven-plugin has the opportunity to access the overlaid resources.
|
||||
|
||||
In the example we'll show, we will use an overlaid war.
|
||||
The overlaid war will provide the web.xml file but the jsps will be in src/main/webapp (ie part of the project that uses the overlay).
|
||||
We will unpack the overlaid war file, compile the jsps and merge their servlet definitions into the extracted web.xml, then war up the lot.
|
||||
The overlaid war will provide the `web.xml` file but the jsps will be in `src/main/webapp` (i.e. part of the project that uses the overlay).
|
||||
We will unpack the overlaid war file, compile the jsps and merge their servlet definitions into the extracted `web.xml`, then pack everything into a war.
|
||||
|
||||
Here's an example configuration of the war plugin that separate those phases into an unpack phase, and then a packing phase:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<plugin>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<executions>
|
||||
|
@ -223,17 +210,14 @@ Here's an example configuration of the war plugin that separate those phases int
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
|
||||
----
|
||||
|
||||
Now you also need to configure the jetty-jspc-maven-plugin so that it can use the web.xml that was extracted by the war unpacking and merge in the generated definitions of the servlets.
|
||||
This is in target/foo/WEB-INF/web.xml.
|
||||
Using the default settings, the web.xml merged with the jsp servlet definitions will be put into target/web.xml.
|
||||
Now you also need to configure the `jetty-jspc-maven-plugin` so that it can use the web.xml that was extracted by the war unpacking and merge in the generated definitions of the servlets.
|
||||
This is in `target/foo/WEB-INF/web.xml`.
|
||||
Using the default settings, the `web.xml` merged with the jsp servlet definitions will be put into `target/web.xml`.
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
|
||||
<plugin>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jspc-maven-plugin</artifactId>
|
||||
|
@ -252,6 +236,4 @@ Using the default settings, the web.xml merged with the jsp servlet definitions
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
|
||||
----
|
||||
|
|
|
@ -23,6 +23,13 @@ Based on the concept of a project object model (POM), Maven can manage a project
|
|||
It is an ideal tool to build a web application project, and such projects can use the link:#jetty-maven-plugin[jetty-maven-plugin] to easily run the web application and save time in development.
|
||||
You can also use Maven to build, test and run a project which embeds Jetty.
|
||||
|
||||
____
|
||||
[NOTE]
|
||||
Use of Maven and the jetty-maven-plugin is *not* required.
|
||||
Using Maven for Jetty implementations is a popular choice, but users encouraged to manage their projects in whatever way suits their needs.
|
||||
Other popular tools include Ant and Gradle.
|
||||
____
|
||||
|
||||
First we'll have a look at a very simple HelloWorld java application that embeds Jetty, then a simple webapp which makes use of the link:#jetty-maven-plugin[jetty-maven-plugin] to speed up the development cycle.
|
||||
|
||||
[[configuring-embedded-jetty-with-maven]]
|
||||
|
@ -30,7 +37,7 @@ First we'll have a look at a very simple HelloWorld java application that embeds
|
|||
|
||||
To understand the basic operations of building and running against Jetty, first review:
|
||||
|
||||
* link:#advanced-embedding[embedding with Jetty]
|
||||
* link:#advanced-embedding[Embedding with Jetty]
|
||||
* link:#jetty-helloworld[Jetty HelloWorld example]
|
||||
|
||||
Maven uses convention over configuration, so it is best to use the project structure Maven recommends.
|
||||
|
@ -65,7 +72,7 @@ public class HelloWorld extends AbstractHandler
|
|||
public void handle(String target,
|
||||
Request baseRequest,
|
||||
HttpServletRequest request,
|
||||
HttpServletResponse response)
|
||||
HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
{
|
||||
response.setContentType("text/html;charset=utf-8");
|
||||
|
@ -78,23 +85,23 @@ public class HelloWorld extends AbstractHandler
|
|||
{
|
||||
Server server = new Server(8080);
|
||||
server.setHandler(new HelloWorld());
|
||||
|
||||
|
||||
server.start();
|
||||
server.join();
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
[[creating-embedded-pom-descriptor]]
|
||||
===== Creating the POM Descriptor
|
||||
|
||||
The `pom.xml` file declares the project name and its dependencies.
|
||||
Use an editor to create the file `pom.xml` with the following contents:
|
||||
Use an editor to create the file `pom.xml` in the `JettyMavenHelloWorld` directory with the following contents:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -108,7 +115,7 @@ Use an editor to create the file `pom.xml` with the following contents:
|
|||
<!-- Adapt this to a version found on
|
||||
http://central.maven.org/maven2/org/eclipse/jetty/jetty-maven-plugin/
|
||||
-->
|
||||
<jettyVersion>9.0.2.v20130417</jettyVersion>
|
||||
<jettyVersion>9.3.9.v20160517</jettyVersion>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
@ -134,7 +141,7 @@ Use an editor to create the file `pom.xml` with the following contents:
|
|||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
</project>
|
||||
----
|
||||
|
||||
[[buildng-and-running-embedded-helloworld]]
|
||||
|
@ -144,36 +151,37 @@ You can now compile and execute the HelloWorld class by using these commands:
|
|||
|
||||
[source, screen, subs="{sub-order}"]
|
||||
....
|
||||
> mvn clean compile exec:java
|
||||
> mvn clean compile exec:java
|
||||
....
|
||||
|
||||
You can point your browser to `http://localhost:8080` to see the hello world page.
|
||||
You can point your browser to `http://localhost:8080` to see the _Hello World_ page.
|
||||
You can observe what Maven is doing for you behind the scenes by using the `mvn dependency:tree` command, which reveals the transitive dependency resolved and downloaded as:
|
||||
|
||||
[source, screen, subs="{sub-order}"]
|
||||
....
|
||||
> mvn dependency:tree
|
||||
[INFO] Scanning for projects...
|
||||
[INFO] Searching repository for plugin with prefix: 'dependency'.
|
||||
...
|
||||
[INFO]
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] Building Jetty HelloWorld
|
||||
[INFO] task-segment: [dependency:tree]
|
||||
[INFO] Building Jetty HelloWorld 0.1-SNAPSHOT
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] [dependency:tree {execution: default-cli}]
|
||||
[INFO]
|
||||
[INFO] --- maven-dependency-plugin:2.8:tree (default-cli) @ hello-world ---
|
||||
...
|
||||
[INFO] org.example:hello-world:jar:0.1-SNAPSHOT
|
||||
[INFO] \- org.eclipse.jetty:jetty-server:jar:9.0.0:compile
|
||||
[INFO] +- org.eclipse.jetty:javax.servlet:jar:3.0.0.v201112011016:compile
|
||||
[INFO] +- org.eclipse.jetty:jetty-continuation:jar:9.0.0:compile
|
||||
[INFO] \- org.eclipse.jetty:jetty-http:jar:9.0.0:compile
|
||||
[INFO] \- org.eclipse.jetty:jetty-io:jar:9.0.0:compile
|
||||
[INFO] \- org.eclipse.jetty:jetty-util:jar:9.0.0:compile
|
||||
[INFO] \- org.eclipse.jetty:jetty-server:jar:9.3.9.v20160517:compile
|
||||
[INFO] +- javax.servlet:javax.servlet-api:jar:3.1.0:compile
|
||||
[INFO] +- org.eclipse.jetty:jetty-http:jar:9.3.9.v20160517:compile
|
||||
[INFO] | \- org.eclipse.jetty:jetty-util:jar:9.3.9.v20160517:compile
|
||||
[INFO] \- org.eclipse.jetty:jetty-io:jar:9.3.9.v20160517:compile
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] BUILD SUCCESSFUL
|
||||
[INFO] BUILD SUCCESS
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] Total time: 4.145 s
|
||||
[INFO] Finished at: 2016-08-01T13:46:42-04:00
|
||||
[INFO] Final Memory: 15M/209M
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
[INFO] Total time: 4 seconds
|
||||
[INFO] Finished at: Thu Jan 24 16:19:08 EST 2013
|
||||
[INFO] Final Memory: 11M/68M
|
||||
[INFO] ------------------------------------------------------------------------
|
||||
....
|
||||
|
||||
[[developing-standard-webapp-with-jetty-and-maven]]
|
||||
|
@ -218,12 +226,12 @@ public class HelloServlet extends HttpServlet
|
|||
}
|
||||
----
|
||||
|
||||
You need to declare this servlet in the deployment descriptor, so edit the file `src/main/webapp/WEB-INF/web.xml` and add the following contents:
|
||||
You need to declare this servlet in the deployment descriptor, so create the file `src/main/webapp/WEB-INF/web.xml` and add the following contents:
|
||||
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<web-app
|
||||
<web-app
|
||||
xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||
|
@ -246,12 +254,12 @@ You need to declare this servlet in the deployment descriptor, so edit the file
|
|||
===== Creating the POM Descriptor
|
||||
|
||||
The `pom.xml` file declares the project name and its dependencies.
|
||||
Use an editor to create the file `pom.xml` with the following contents, noting particularly the declaration of the link:#jetty-maven-plugin[jetty-maven-plugin]:
|
||||
Use an editor to create the file `pom.xml` with the following contents in the `JettyMavenHelloWarApp` directory, noting particularly the declaration of the link:#jetty-maven-plugin[jetty-maven-plugin]:
|
||||
|
||||
[source, java, subs="{sub-order}"]
|
||||
[source, xml, subs="{sub-order}"]
|
||||
----
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
@ -284,7 +292,7 @@ Use an editor to create the file `pom.xml` with the following contents, noting p
|
|||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
----
|
||||
|
||||
[[building-and-running-web-application]]
|
||||
|
@ -309,7 +317,7 @@ You can create a Web Application Archive (WAR) file from the project with the co
|
|||
|
||||
[source, screen, subs="{sub-order}"]
|
||||
....
|
||||
> mvn package
|
||||
> mvn package
|
||||
....
|
||||
|
||||
The resulting war file is in the `target` directory and may be deployed on any standard servlet server, including link:#configuring-deployment[Jetty].
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -17,15 +17,15 @@
|
|||
[[jetty-maven-scanning]]
|
||||
=== Files Scanned by the Jetty Maven Plugin
|
||||
|
||||
If you set a non zero *scanInterval* link:#jetty-maven-plugin[configuration parameter], the jetty maven plugin will scan certain files every *scanInterval* seconds for changes, and redeploy the webapp if necessary.
|
||||
If you set a non zero `scanInterval` link:#jetty-maven-plugin[configuration parameter], the `jetty-maven-plugin` will scan certain files every `scanInterval` seconds for changes, and redeploy the webapp if necessary.
|
||||
The files that are scanned depend on the goal being executed.
|
||||
|
||||
[[scanner-matrix]]
|
||||
==== Scanner Matrix
|
||||
|
||||
[width="100%",cols="<100%",options="header",]
|
||||
[width="100%",cols="2",options="header"]
|
||||
|=======================================================================
|
||||
|Goal |Files
|
||||
|Goal |Files
|
||||
|link:#jetty-run-goal[jetty:run] |pom.xml, <dependencies>, <classesDirectory>, <testClassesDirectory>, <webXml> or <webAppSourceDirectory>/WEB-INF/web.xml, <jettyEnvXml> or <webAppSourceDirectory>/WEB-INF/jetty-web.xml, <webAppSourceDirectory>/WEB-INF/jetty-web.xml, <scanTargets>, <scanTargetPatterns>, any link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html#setDefaultsDescriptor%28java.lang.String%29[defaultsDescriptor] for the webapp, any link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html#setOverrideDescriptor%28java.lang.String%29[overrideDescriptor] for the webapp
|
||||
|link:#running-assembled-webapp-as-war[jetty:run-war] |pom.xml, <war>
|
||||
|link:#running-assembled-webapp-as-expanded-war[jetty:run-exploded]
|
||||
|
|
|
@ -30,7 +30,9 @@ import java.util.HashSet;
|
|||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.MissingResourceException;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.jetty.util.ArrayTrie;
|
||||
|
@ -201,79 +203,49 @@ public class MimeTypes
|
|||
}
|
||||
}
|
||||
|
||||
String resourceName = "org/eclipse/jetty/http/mime";
|
||||
try
|
||||
{
|
||||
String resourceName = "org/eclipse/jetty/http/mime.properties";
|
||||
URL mimeTypesUrl = Loader.getResource(resourceName);
|
||||
if (mimeTypesUrl == null)
|
||||
ResourceBundle mimeBundle = ResourceBundle.getBundle(resourceName);
|
||||
mimeBundle.keySet().stream()
|
||||
.filter(x->x!=null)
|
||||
.forEach(x->
|
||||
__dftMimeMap.put(StringUtil.asciiToLowerCase(x), normalizeMimeType(mimeBundle.getString(x))));
|
||||
|
||||
if (__dftMimeMap.size()==0)
|
||||
{
|
||||
LOG.warn("Missing mime-type resource: {}", resourceName);
|
||||
LOG.warn("Empty mime types at {}", resourceName);
|
||||
}
|
||||
else
|
||||
else if (__dftMimeMap.size()<mimeBundle.keySet().size())
|
||||
{
|
||||
try (InputStream in = mimeTypesUrl.openStream();
|
||||
InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8))
|
||||
{
|
||||
Properties mime = new Properties();
|
||||
mime.load(reader);
|
||||
mime.stringPropertyNames().stream()
|
||||
.filter(x->x!=null)
|
||||
.forEach(x->
|
||||
__dftMimeMap.put(StringUtil.asciiToLowerCase(x), normalizeMimeType(mime.getProperty(x))));
|
||||
|
||||
if (__dftMimeMap.size()<mime.size())
|
||||
{
|
||||
LOG.warn("Encountered duplicate or null mime-type extension in resource: {}", mimeTypesUrl);
|
||||
}
|
||||
}
|
||||
if (__dftMimeMap.size()==0)
|
||||
{
|
||||
LOG.warn("Empty mime types declaration at {}", mimeTypesUrl);
|
||||
}
|
||||
}
|
||||
LOG.warn("Duplicate or null mime-type extension in resource: {}", resourceName);
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
catch (MissingResourceException e)
|
||||
{
|
||||
LOG.warn(e.toString());
|
||||
LOG.debug(e);
|
||||
LOG.warn("Missing mime-type resource: {}", resourceName);
|
||||
}
|
||||
|
||||
resourceName = "org/eclipse/jetty/http/encoding";
|
||||
try
|
||||
{
|
||||
String resourceName = "org/eclipse/jetty/http/encoding.properties";
|
||||
URL mimeTypesUrl = Loader.getResource(resourceName);
|
||||
if (mimeTypesUrl == null)
|
||||
ResourceBundle encodingBundle = ResourceBundle.getBundle(resourceName);
|
||||
encodingBundle.keySet().stream()
|
||||
.filter(t->t!=null)
|
||||
.forEach(t->__encodings.put(t, encodingBundle.getString(t)));
|
||||
|
||||
if (__encodings.size()==0)
|
||||
{
|
||||
LOG.warn("Missing mime-type resource: {}", resourceName);
|
||||
LOG.warn("Empty encodings at {}", resourceName);
|
||||
}
|
||||
else
|
||||
else if (__encodings.size()<encodingBundle.keySet().size())
|
||||
{
|
||||
try (InputStream in = mimeTypesUrl.openStream();
|
||||
InputStreamReader reader = new InputStreamReader(in, StandardCharsets.UTF_8))
|
||||
{
|
||||
Properties encoding = new Properties();
|
||||
encoding.load(reader);
|
||||
|
||||
encoding.stringPropertyNames().stream()
|
||||
.filter(t->t!=null)
|
||||
.forEach(t->__encodings.put(t, encoding.getProperty(t)));
|
||||
|
||||
if (__encodings.size()<encoding.size())
|
||||
{
|
||||
LOG.warn("Encountered null or duplicate encoding type in resource: {}", mimeTypesUrl);
|
||||
}
|
||||
}
|
||||
|
||||
if (__encodings.size()==0)
|
||||
{
|
||||
LOG.warn("Empty mime types declaration at {}", mimeTypesUrl);
|
||||
}
|
||||
LOG.warn("Null or duplicate encodings in resource: {}", resourceName);
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
catch (MissingResourceException e)
|
||||
{
|
||||
LOG.warn(e.toString());
|
||||
LOG.debug(e);
|
||||
LOG.warn("Missing encoding resource: {}", resourceName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ public class MaxConcurrentStreamsTest extends AbstractTest
|
|||
@Test
|
||||
public void testOneConcurrentStream() throws Exception
|
||||
{
|
||||
long sleep = 1000;
|
||||
long sleep = 2000;
|
||||
start(1, new AbstractHandler()
|
||||
{
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
[description]
|
||||
Enables session data store in a local Infinispan cache
|
||||
|
||||
[provides]
|
||||
session-store
|
||||
|
||||
[depend]
|
||||
sessions
|
||||
sessions/infinispan/default
|
||||
|
||||
[files]
|
||||
maven://org.infinispan/infinispan-embedded/7.1.1.Final|lib/infinispan/infinispan-embedded-7.1.1.Final.jar
|
||||
|
||||
[lib]
|
||||
lib/jetty-infinispan-${jetty.version}.jar
|
||||
lib/infinispan/*.jar
|
||||
|
||||
[license]
|
||||
Infinispan is an open source project hosted on Github and released under the Apache 2.0 license.
|
||||
http://infinispan.org/
|
||||
http://www.apache.org/licenses/LICENSE-2.0.html
|
|
@ -0,0 +1,27 @@
|
|||
[description]
|
||||
Enables session data store in a remote Infinispan cache
|
||||
|
||||
[provides]
|
||||
session-store
|
||||
|
||||
[depend]
|
||||
sessions
|
||||
sessions/infinispan/remote
|
||||
|
||||
[files]
|
||||
maven://org.infinispan/infinispan-remote/7.1.1.Final|lib/infinispan/infinispan-remote-7.1.1.Final.jar
|
||||
|
||||
[lib]
|
||||
lib/jetty-infinispan-${jetty.version}.jar
|
||||
lib/infinispan/*.jar
|
||||
|
||||
[license]
|
||||
Infinispan is an open source project hosted on Github and released under the Apache 2.0 license.
|
||||
http://infinispan.org/
|
||||
http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
|
||||
[ini-template]
|
||||
#jetty.session.remoteInfinispanCache.name=sessions
|
||||
#jetty.session.infinispanIdleTimeout.seconds=0
|
||||
#jetty.session.gracePeriod.seconds=3600
|
|
@ -1,37 +0,0 @@
|
|||
[description]
|
||||
Enables session data store in an Infinispan cache
|
||||
|
||||
[provides]
|
||||
session-store
|
||||
|
||||
[depend]
|
||||
sessions
|
||||
sessions/infinispan/${cache-type}
|
||||
|
||||
[files]
|
||||
maven://org.infinispan/infinispan-core/7.1.1.Final|lib/infinispan/infinispan-core-7.1.1.Final.jar
|
||||
maven://org.infinispan/infinispan-commons/7.1.1.Final|lib/infinispan/infinispan-commons-7.1.1.Final.jar
|
||||
maven://org.jgroups/jgroups/3.6.1.Final|lib/infinispan/jgroups-3.6.1.Final.jar
|
||||
maven://org.jboss.marshalling/jboss-marshalling-osgi/1.4.4.Final|lib/infinispan/jboss-marshalling-osgi-1.4.4.Final.jar
|
||||
maven://org.jboss.logging/jboss-logging/3.1.2.GA|lib/infinispan/jboss-logging-3.1.2.GA.jar
|
||||
|
||||
[lib]
|
||||
lib/jetty-infinispan-${jetty.version}.jar
|
||||
lib/infinispan/*.jar
|
||||
|
||||
[license]
|
||||
Infinispan is an open source project hosted on Github and released under the Apache 2.0 license.
|
||||
http://infinispan.org/
|
||||
http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
|
||||
[ini]
|
||||
cache-type=default
|
||||
|
||||
[ini-template]
|
||||
cache-type=default
|
||||
|
||||
#cache-type=remote
|
||||
#jetty.session.remoteInfinispanCache.name=sessions
|
||||
#jetty.session.infinispanIdleTimeout.seconds=0
|
||||
#jetty.session.gracePeriod.seconds=3600
|
|
@ -268,7 +268,7 @@ public class ByteArrayEndPointTest
|
|||
@Test
|
||||
public void testIdle() throws Exception
|
||||
{
|
||||
long idleTimeout = 500;
|
||||
long idleTimeout = 1500;
|
||||
ByteArrayEndPoint endp = new ByteArrayEndPoint(_scheduler, idleTimeout);
|
||||
endp.addInput("test");
|
||||
endp.setGrowOutput(false);
|
||||
|
@ -284,7 +284,7 @@ public class ByteArrayEndPointTest
|
|||
FutureCallback fcb = new FutureCallback();
|
||||
|
||||
endp.fillInterested(fcb);
|
||||
fcb.get(100,TimeUnit.MILLISECONDS);
|
||||
fcb.get(idleTimeout,TimeUnit.MILLISECONDS);
|
||||
assertTrue(fcb.isDone());
|
||||
assertEquals(null, fcb.get());
|
||||
assertEquals(4, endp.fill(buffer));
|
||||
|
|
|
@ -43,6 +43,8 @@ import javax.security.auth.callback.UnsupportedCallbackException;
|
|||
import javax.security.auth.login.LoginException;
|
||||
|
||||
import org.eclipse.jetty.jaas.callback.ObjectCallback;
|
||||
import org.eclipse.jetty.util.B64Code;
|
||||
import org.eclipse.jetty.util.TypeUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.security.Credential;
|
||||
|
@ -687,38 +689,36 @@ public class LdapLoginModule extends AbstractLoginModule
|
|||
return env;
|
||||
}
|
||||
|
||||
public static String convertCredentialJettyToLdap(String encryptedPassword)
|
||||
{
|
||||
if ("MD5:".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
{
|
||||
return "{MD5}" + encryptedPassword.substring("MD5:".length(), encryptedPassword.length());
|
||||
}
|
||||
|
||||
if ("CRYPT:".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
{
|
||||
return "{CRYPT}" + encryptedPassword.substring("CRYPT:".length(), encryptedPassword.length());
|
||||
}
|
||||
|
||||
return encryptedPassword;
|
||||
}
|
||||
|
||||
public static String convertCredentialLdapToJetty(String encryptedPassword)
|
||||
{
|
||||
if (encryptedPassword == null)
|
||||
{
|
||||
return encryptedPassword;
|
||||
return null;
|
||||
}
|
||||
|
||||
if ("{MD5}".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
if (encryptedPassword.toUpperCase(Locale.ENGLISH).startsWith("{MD5}"))
|
||||
{
|
||||
return "MD5:" + encryptedPassword.substring("{MD5}".length(), encryptedPassword.length());
|
||||
String src = encryptedPassword.substring("{MD5}".length(), encryptedPassword.length());
|
||||
return "MD5:" + base64ToHex(src);
|
||||
}
|
||||
|
||||
if ("{CRYPT}".startsWith(encryptedPassword.toUpperCase(Locale.ENGLISH)))
|
||||
if (encryptedPassword.toUpperCase(Locale.ENGLISH).startsWith("{CRYPT}"))
|
||||
{
|
||||
return "CRYPT:" + encryptedPassword.substring("{CRYPT}".length(), encryptedPassword.length());
|
||||
}
|
||||
|
||||
return encryptedPassword;
|
||||
}
|
||||
|
||||
private static String base64ToHex(String src)
|
||||
{
|
||||
byte[] bytes = B64Code.decode(src);
|
||||
return TypeUtil.toString(bytes, 16);
|
||||
}
|
||||
|
||||
private static String hexToBase64(String src)
|
||||
{
|
||||
byte[] bytes = TypeUtil.fromHexString(src);
|
||||
return new String(B64Code.encode(bytes));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,11 +73,11 @@
|
|||
org.xml.sax.helpers,
|
||||
*
|
||||
</Import-Package>
|
||||
<Export-Package>com.acme.osgi</Export-Package>
|
||||
<DynamicImport-Package>org.eclipse.jetty.*;version="[$(version;===;${parsedVersion.osgiVersion}),$(version;==+;${parsedVersion.osgiVersion}))"</DynamicImport-Package>
|
||||
</instructions>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -18,10 +18,18 @@
|
|||
|
||||
package com.acme.osgi;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Dictionary;
|
||||
import java.util.Hashtable;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.osgi.framework.BundleActivator;
|
||||
import org.osgi.framework.BundleContext;
|
||||
|
@ -37,6 +45,27 @@ public class Activator implements BundleActivator
|
|||
|
||||
private ServiceRegistration _srA;
|
||||
private ServiceRegistration _srB;
|
||||
|
||||
public static class TestServlet extends HttpServlet
|
||||
{
|
||||
|
||||
/**
|
||||
* @see javax.servlet.http.HttpServlet#doGet(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
|
||||
*/
|
||||
@Override
|
||||
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
|
||||
{
|
||||
//report the mimetype of a file
|
||||
String mimetype = req.getServletContext().getMimeType("file.gz");
|
||||
resp.setContentType("text/html");
|
||||
PrintWriter writer = resp.getWriter();
|
||||
writer.write("<html><body><p>MIMETYPE="+mimetype+"</p></body</html>");
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -44,12 +73,9 @@ public class Activator implements BundleActivator
|
|||
*/
|
||||
public void start(BundleContext context) throws Exception
|
||||
{
|
||||
String serverName = "defaultJettyServer";
|
||||
|
||||
|
||||
|
||||
//Create webappA as a Service and target it at the default server
|
||||
WebAppContext webapp = new WebAppContext();
|
||||
webapp.addServlet(new ServletHolder(new TestServlet()), "/mime");
|
||||
Dictionary props = new Hashtable();
|
||||
props.put("war","webappA");
|
||||
props.put("contextPath","/acme");
|
||||
|
|
|
@ -150,6 +150,11 @@ public class TestJettyOSGiBootWebAppAsService
|
|||
String content = new String(response.getContent());
|
||||
assertTrue(content.indexOf("<h1>Test OSGi WebAppA</h1>") != -1);
|
||||
|
||||
response = client.GET("http://127.0.0.1:" + TestJettyOSGiBootCore.DEFAULT_HTTP_PORT + "/acme/mime");
|
||||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
content = new String(response.getContent());
|
||||
assertTrue(content.indexOf("MIMETYPE=application/gzip") != -1);
|
||||
|
||||
response = client.GET("http://127.0.0.1:" + "9999" + "/acme/index.html");
|
||||
assertEquals(HttpStatus.OK_200, response.getStatus());
|
||||
content = new String(response.getContent());
|
||||
|
|
|
@ -55,9 +55,18 @@ public abstract class NamingEntry
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create a naming entry.
|
||||
*
|
||||
* @param scope an object representing the scope of the name to be bound into jndi, where null means jvm scope.
|
||||
* @param jndiName the name that will be associated with an object bound into jndi
|
||||
* @throws NamingException
|
||||
*/
|
||||
protected NamingEntry (Object scope, String jndiName)
|
||||
throws NamingException
|
||||
{
|
||||
if (jndiName == null)
|
||||
throw new NamingException("jndi name is null");
|
||||
this._scope=scope;
|
||||
this._jndiName = jndiName;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse;
|
|||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Hashtable;
|
||||
|
@ -238,6 +239,35 @@ public class TestNamingEntries
|
|||
testLink();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNullJndiName () throws Exception
|
||||
{
|
||||
try
|
||||
{
|
||||
InitialContext icontext = new InitialContext();
|
||||
Resource resource = new Resource (null,"foo");
|
||||
fail ("Null jndi name should not be permitted");
|
||||
}
|
||||
catch (NamingException e)
|
||||
{
|
||||
//expected
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNullObject () throws Exception
|
||||
{
|
||||
InitialContext icontext = new InitialContext();
|
||||
Resource resource = new Resource ("foo/bar", null);
|
||||
NamingEntry ne = NamingEntryUtil.lookupNamingEntry(null, "foo/bar");
|
||||
assertNotNull(ne);
|
||||
Object o = icontext.lookup("foo/bar");
|
||||
assertNull(o);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLink () throws Exception
|
||||
{
|
||||
|
|
|
@ -146,6 +146,12 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
_state.set(OutputState.OPEN);
|
||||
}
|
||||
|
||||
private boolean isLastContentToWrite(int len)
|
||||
{
|
||||
_written+=len;
|
||||
return _channel.getResponse().isAllContentWritten(_written);
|
||||
}
|
||||
|
||||
public boolean isAllContentWritten()
|
||||
{
|
||||
return _channel.getResponse().isAllContentWritten(_written);
|
||||
|
@ -370,9 +376,6 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException
|
||||
{
|
||||
_written+=len;
|
||||
boolean complete=_channel.getResponse().isAllContentWritten(_written);
|
||||
|
||||
// Async or Blocking ?
|
||||
while(true)
|
||||
{
|
||||
|
@ -390,7 +393,8 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
continue;
|
||||
|
||||
// Should we aggregate?
|
||||
if (!complete && len<=_commitSize)
|
||||
boolean last = isLastContentToWrite(len);
|
||||
if (!last && len<=_commitSize)
|
||||
{
|
||||
if (_aggregate == null)
|
||||
_aggregate = _channel.getByteBufferPool().acquire(getBufferSize(), _interceptor.isOptimizedForDirectBuffers());
|
||||
|
@ -412,7 +416,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
}
|
||||
|
||||
// Do the asynchronous writing from the callback
|
||||
new AsyncWrite(b,off,len,complete).iterate();
|
||||
new AsyncWrite(b,off,len,last).iterate();
|
||||
return;
|
||||
|
||||
case PENDING:
|
||||
|
@ -435,7 +439,8 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
|
||||
// Should we aggregate?
|
||||
int capacity = getBufferSize();
|
||||
if (!complete && len<=_commitSize)
|
||||
boolean last = isLastContentToWrite(len);
|
||||
if (!last && len<=_commitSize)
|
||||
{
|
||||
if (_aggregate == null)
|
||||
_aggregate = _channel.getByteBufferPool().acquire(capacity, _interceptor.isOptimizedForDirectBuffers());
|
||||
|
@ -455,10 +460,10 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
// flush any content from the aggregate
|
||||
if (BufferUtil.hasContent(_aggregate))
|
||||
{
|
||||
write(_aggregate, complete && len==0);
|
||||
write(_aggregate, last && len==0);
|
||||
|
||||
// should we fill aggregate again from the buffer?
|
||||
if (len>0 && !complete && len<=_commitSize && len<=BufferUtil.space(_aggregate))
|
||||
if (len>0 && !last && len<=_commitSize && len<=BufferUtil.space(_aggregate))
|
||||
{
|
||||
BufferUtil.append(_aggregate, b, off, len);
|
||||
return;
|
||||
|
@ -481,22 +486,19 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
view.limit(l+Math.min(len,getBufferSize()));
|
||||
view.position(l);
|
||||
}
|
||||
write(view,complete);
|
||||
write(view,last);
|
||||
}
|
||||
else if (complete)
|
||||
else if (last)
|
||||
{
|
||||
write(BufferUtil.EMPTY_BUFFER,true);
|
||||
}
|
||||
|
||||
if (complete)
|
||||
if (last)
|
||||
closed();
|
||||
}
|
||||
|
||||
public void write(ByteBuffer buffer) throws IOException
|
||||
{
|
||||
_written+=buffer.remaining();
|
||||
boolean complete=_channel.getResponse().isAllContentWritten(_written);
|
||||
|
||||
// Async or Blocking ?
|
||||
while(true)
|
||||
{
|
||||
|
@ -514,7 +516,8 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
continue;
|
||||
|
||||
// Do the asynchronous writing from the callback
|
||||
new AsyncWrite(buffer,complete).iterate();
|
||||
boolean last = isLastContentToWrite(buffer.remaining());
|
||||
new AsyncWrite(buffer,last).iterate();
|
||||
return;
|
||||
|
||||
case PENDING:
|
||||
|
@ -536,18 +539,19 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
|
||||
// handle blocking write
|
||||
int len=BufferUtil.length(buffer);
|
||||
boolean last = isLastContentToWrite(len);
|
||||
|
||||
// flush any content from the aggregate
|
||||
if (BufferUtil.hasContent(_aggregate))
|
||||
write(_aggregate, complete && len==0);
|
||||
write(_aggregate, last && len==0);
|
||||
|
||||
// write any remaining content in the buffer directly
|
||||
if (len>0)
|
||||
write(buffer, complete);
|
||||
else if (complete)
|
||||
write(buffer, last);
|
||||
else if (last)
|
||||
write(BufferUtil.EMPTY_BUFFER, true);
|
||||
|
||||
if (complete)
|
||||
if (last)
|
||||
closed();
|
||||
}
|
||||
|
||||
|
@ -1009,6 +1013,13 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
|
||||
private abstract class AsyncICB extends IteratingCallback
|
||||
{
|
||||
final boolean _last;
|
||||
|
||||
AsyncICB(boolean last)
|
||||
{
|
||||
_last=last;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCompleteSuccess()
|
||||
{
|
||||
|
@ -1025,6 +1036,8 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
case UNREADY:
|
||||
if (!_state.compareAndSet(OutputState.UNREADY, OutputState.READY))
|
||||
continue;
|
||||
if (_last)
|
||||
closed();
|
||||
if (_channel.getState().onWritePossible())
|
||||
_channel.execute(_channel);
|
||||
break;
|
||||
|
@ -1054,6 +1067,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
|
||||
public AsyncFlush()
|
||||
{
|
||||
super(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1081,21 +1095,21 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
{
|
||||
private final ByteBuffer _buffer;
|
||||
private final ByteBuffer _slice;
|
||||
private final boolean _complete;
|
||||
private final int _len;
|
||||
protected volatile boolean _completed;
|
||||
|
||||
public AsyncWrite(byte[] b, int off, int len, boolean complete)
|
||||
public AsyncWrite(byte[] b, int off, int len, boolean last)
|
||||
{
|
||||
super(last);
|
||||
_buffer=ByteBuffer.wrap(b, off, len);
|
||||
_len=len;
|
||||
// always use a view for large byte arrays to avoid JVM pooling large direct buffers
|
||||
_slice=_len<getBufferSize()?null:_buffer.duplicate();
|
||||
_complete=complete;
|
||||
}
|
||||
|
||||
public AsyncWrite(ByteBuffer buffer, boolean complete)
|
||||
public AsyncWrite(ByteBuffer buffer, boolean last)
|
||||
{
|
||||
super(last);
|
||||
_buffer=buffer;
|
||||
_len=buffer.remaining();
|
||||
// Use a slice buffer for large indirect to avoid JVM pooling large direct buffers
|
||||
|
@ -1104,9 +1118,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
else
|
||||
{
|
||||
_slice=_buffer.duplicate();
|
||||
_buffer.position(_buffer.limit());
|
||||
}
|
||||
_complete=complete;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1116,12 +1128,12 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
if (BufferUtil.hasContent(_aggregate))
|
||||
{
|
||||
_completed=_len==0;
|
||||
write(_aggregate, _complete && _completed, this);
|
||||
write(_aggregate, _last && _completed, this);
|
||||
return Action.SCHEDULED;
|
||||
}
|
||||
|
||||
// Can we just aggregate the remainder?
|
||||
if (!_complete && _len<BufferUtil.space(_aggregate) && _len<_commitSize)
|
||||
if (!_last && _len<BufferUtil.space(_aggregate) && _len<_commitSize)
|
||||
{
|
||||
int position = BufferUtil.flipToFill(_aggregate);
|
||||
BufferUtil.put(_buffer,_aggregate);
|
||||
|
@ -1136,7 +1148,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
if (_slice==null)
|
||||
{
|
||||
_completed=true;
|
||||
write(_buffer, _complete, this);
|
||||
write(_buffer, _last, this);
|
||||
return Action.SCHEDULED;
|
||||
}
|
||||
|
||||
|
@ -1148,13 +1160,13 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
_buffer.position(pl);
|
||||
_slice.position(p);
|
||||
_completed=!_buffer.hasRemaining();
|
||||
write(_slice, _complete && _completed, this);
|
||||
write(_slice, _last && _completed, this);
|
||||
return Action.SCHEDULED;
|
||||
}
|
||||
|
||||
// all content written, but if we have not yet signal completion, we
|
||||
// need to do so
|
||||
if (_complete && !_completed)
|
||||
if (_last && !_completed)
|
||||
{
|
||||
_completed=true;
|
||||
write(BufferUtil.EMPTY_BUFFER, true, this);
|
||||
|
@ -1165,14 +1177,6 @@ public class HttpOutput extends ServletOutputStream implements Runnable
|
|||
LOG.debug("EOF of {}",this);
|
||||
return Action.SUCCEEDED;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCompleteSuccess()
|
||||
{
|
||||
super.onCompleteSuccess();
|
||||
if (_complete)
|
||||
closed();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -344,7 +344,7 @@ public class Response implements HttpServletResponse
|
|||
}
|
||||
|
||||
// add the set cookie
|
||||
_fields.add(HttpHeader.SET_COOKIE.toString(), buf.toString());
|
||||
_fields.add(HttpHeader.SET_COOKIE, buf.toString());
|
||||
|
||||
// Expire responses with set-cookie headers so they do not get cached.
|
||||
_fields.put(__EXPIRES_01JAN1970);
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
|
@ -140,6 +141,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -164,6 +166,7 @@ public class HttpOutputTest
|
|||
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,containsString("Transfer-Encoding: chunked"));
|
||||
assertThat(response, containsString("1\tThis is a big file"));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response,containsString("\r\n0\r\n"));
|
||||
|
||||
|
@ -191,7 +194,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -202,7 +205,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,containsString("Content-Length"));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -213,7 +216,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,containsString("Content-Length"));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -261,6 +264,8 @@ public class HttpOutputTest
|
|||
String response = endp.getResponse();
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,containsString("Transfer-Encoding: chunked"));
|
||||
assertThat(response, containsString("1\tThis is a big file"));
|
||||
assertThat(response, containsString("400\tThis is a big file"));
|
||||
assertThat(response,containsString("\r\n0\r\n"));
|
||||
|
||||
response = endp.getResponse();
|
||||
|
@ -279,7 +284,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -293,7 +298,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -307,7 +312,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -321,7 +326,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -335,7 +340,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,containsString("Content-Length"));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -349,7 +354,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,containsString("Content-Length"));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -363,7 +368,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,containsString("Content-Length"));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -377,7 +382,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,containsString("Content-Length"));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -408,7 +413,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -422,7 +427,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -436,7 +441,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -452,7 +457,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -467,7 +472,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -482,7 +487,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -497,7 +502,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -531,7 +536,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -546,7 +551,7 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -561,7 +566,23 @@ public class HttpOutputTest
|
|||
String response=_connector.getResponse("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tThis is a big file"));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAsyncWriteBufferLargeDirect()
|
||||
throws Exception
|
||||
{
|
||||
final Resource big = Resource.newClassPathResource("simple/big.txt");
|
||||
_handler._writeLengthIfKnown = false;
|
||||
_handler._content = BufferUtil.toBuffer(big, true);
|
||||
_handler._byteBuffer = BufferUtil.allocateDirect(8192);
|
||||
_handler._async = true;
|
||||
|
||||
String response = _connector.getResponses("GET / HTTP/1.0\nHost: localhost:80\n\n");
|
||||
assertThat(response, containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response, Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response, endsWith(toUTF8String(big)));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -578,7 +599,8 @@ public class HttpOutputTest
|
|||
assertThat(_handler._owp.get()-start,Matchers.greaterThan(0));
|
||||
assertThat(response,containsString("HTTP/1.1 200 OK"));
|
||||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,Matchers.not(containsString("400\tThis is a big file")));
|
||||
assertThat(response, Matchers.not(containsString("1\tThis is a big file")));
|
||||
assertThat(response, Matchers.not(containsString("400\tThis is a big file")));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -657,6 +679,12 @@ public class HttpOutputTest
|
|||
assertThat(response,Matchers.not(containsString("Content-Length")));
|
||||
assertThat(response,containsString("400\tTHIS IS A BIGGER FILE"));
|
||||
}
|
||||
|
||||
private static String toUTF8String(Resource resource)
|
||||
throws IOException
|
||||
{
|
||||
return BufferUtil.toUTF8String(BufferUtil.toBuffer(resource, false));
|
||||
}
|
||||
|
||||
interface ChainedInterceptor extends HttpOutput.Interceptor
|
||||
{
|
||||
|
@ -775,6 +803,8 @@ public class HttpOutputTest
|
|||
final AsyncContext async = request.startAsync();
|
||||
out.setWriteListener(new WriteListener()
|
||||
{
|
||||
private boolean isFirstWrite = true;
|
||||
|
||||
@Override
|
||||
public void onWritePossible() throws IOException
|
||||
{
|
||||
|
@ -782,6 +812,7 @@ public class HttpOutputTest
|
|||
|
||||
while (out.isReady())
|
||||
{
|
||||
Assert.assertTrue(isFirstWrite || !_byteBuffer.hasRemaining());
|
||||
Assert.assertTrue(out.isReady());
|
||||
if(BufferUtil.isEmpty(_content))
|
||||
{
|
||||
|
@ -793,6 +824,7 @@ public class HttpOutputTest
|
|||
BufferUtil.put(_content,_byteBuffer);
|
||||
BufferUtil.flipToFlush(_byteBuffer,0);
|
||||
out.write(_byteBuffer);
|
||||
isFirstWrite = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,11 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
@ -42,7 +47,9 @@ import javax.servlet.ServletOutputStream;
|
|||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.eclipse.jetty.http.HttpField;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeader;
|
||||
import org.eclipse.jetty.http.HttpURI;
|
||||
|
@ -139,7 +146,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testContentType() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
assertEquals(null, response.getContentType());
|
||||
|
||||
|
@ -244,7 +251,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testStrangeContentType() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
assertEquals(null, response.getContentType());
|
||||
|
||||
|
@ -258,7 +265,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testLocale() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
ContextHandler context = new ContextHandler();
|
||||
context.addLocaleEncoding(Locale.ENGLISH.toString(), "ISO-8859-1");
|
||||
|
@ -281,7 +288,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testContentTypeCharacterEncoding() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
response.setContentType("foo/bar");
|
||||
response.setCharacterEncoding("utf-8");
|
||||
|
@ -309,7 +316,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testCharacterEncodingContentType() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("foo/bar");
|
||||
assertEquals("foo/bar;charset=utf-8", response.getContentType());
|
||||
|
@ -336,7 +343,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testContentTypeWithCharacterEncoding() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
response.setCharacterEncoding("utf16");
|
||||
response.setContentType("foo/bar; charset=UTF-8");
|
||||
|
@ -372,10 +379,45 @@ public class ResponseTest
|
|||
assertEquals("foo/bar;charset=utf-8", response.getContentType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResetWithNewSession() throws Exception
|
||||
{
|
||||
Response response = getResponse();
|
||||
Request request = response.getHttpChannel().getRequest();
|
||||
|
||||
SessionHandler session_handler = new SessionHandler();
|
||||
session_handler.setServer(_server);
|
||||
session_handler.setUsingCookies(true);
|
||||
session_handler.start();
|
||||
request.setSessionHandler(session_handler);
|
||||
HttpSession session = request.getSession(true);
|
||||
|
||||
assertThat(session,not(nullValue()));
|
||||
assertTrue(session.isNew());
|
||||
|
||||
HttpField set_cookie = response.getHttpFields().getField(HttpHeader.SET_COOKIE);
|
||||
assertThat(set_cookie,not(nullValue()));
|
||||
assertThat(set_cookie.getValue(),startsWith("JSESSIONID"));
|
||||
assertThat(set_cookie.getValue(),containsString(session.getId()));
|
||||
response.setHeader("Some","Header");
|
||||
response.addCookie(new Cookie("Some","Cookie"));
|
||||
response.getOutputStream().print("X");
|
||||
assertThat(response.getHttpFields().size(),is(4));
|
||||
|
||||
response.reset();
|
||||
|
||||
set_cookie = response.getHttpFields().getField(HttpHeader.SET_COOKIE);
|
||||
assertThat(set_cookie,not(nullValue()));
|
||||
assertThat(set_cookie.getValue(),startsWith("JSESSIONID"));
|
||||
assertThat(set_cookie.getValue(),containsString(session.getId()));
|
||||
assertThat(response.getHttpFields().size(),is(2));
|
||||
response.getWriter();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResetContentTypeWithoutCharacterEncoding() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
response.setCharacterEncoding("utf-8");
|
||||
response.setContentType("wrong/answer");
|
||||
|
@ -390,7 +432,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testResetContentTypeWithCharacterEncoding() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
response.setContentType("wrong/answer;charset=utf-8");
|
||||
response.setContentType("foo/bar");
|
||||
|
@ -407,7 +449,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testContentTypeWithOther() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
response.setContentType("foo/bar; other=xyz");
|
||||
assertEquals("foo/bar; other=xyz", response.getContentType());
|
||||
|
@ -430,7 +472,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testContentTypeWithCharacterEncodingAndOther() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
response.setCharacterEncoding("utf16");
|
||||
response.setContentType("foo/bar; charset=utf-8 other=xyz");
|
||||
|
@ -458,26 +500,26 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testStatusCodes() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
response.sendError(404);
|
||||
assertEquals(404, response.getStatus());
|
||||
assertEquals("Not Found", response.getReason());
|
||||
|
||||
response = newResponse();
|
||||
response = getResponse();
|
||||
|
||||
response.sendError(500, "Database Error");
|
||||
assertEquals(500, response.getStatus());
|
||||
assertEquals("Database Error", response.getReason());
|
||||
assertEquals("must-revalidate,no-cache,no-store", response.getHeader(HttpHeader.CACHE_CONTROL.asString()));
|
||||
|
||||
response = newResponse();
|
||||
response = getResponse();
|
||||
|
||||
response.setStatus(200);
|
||||
assertEquals(200, response.getStatus());
|
||||
assertEquals(null, response.getReason());
|
||||
|
||||
response = newResponse();
|
||||
response = getResponse();
|
||||
|
||||
response.sendError(406, "Super Nanny");
|
||||
assertEquals(406, response.getStatus());
|
||||
|
@ -489,26 +531,26 @@ public class ResponseTest
|
|||
public void testStatusCodesNoErrorHandler() throws Exception
|
||||
{
|
||||
_server.removeBean(_server.getBean(ErrorHandler.class));
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
response.sendError(404);
|
||||
assertEquals(404, response.getStatus());
|
||||
assertEquals("Not Found", response.getReason());
|
||||
|
||||
response = newResponse();
|
||||
response = getResponse();
|
||||
|
||||
response.sendError(500, "Database Error");
|
||||
assertEquals(500, response.getStatus());
|
||||
assertEquals("Database Error", response.getReason());
|
||||
assertThat(response.getHeader(HttpHeader.CACHE_CONTROL.asString()),Matchers.nullValue());
|
||||
|
||||
response = newResponse();
|
||||
response = getResponse();
|
||||
|
||||
response.setStatus(200);
|
||||
assertEquals(200, response.getStatus());
|
||||
assertEquals(null, response.getReason());
|
||||
|
||||
response = newResponse();
|
||||
response = getResponse();
|
||||
|
||||
response.sendError(406, "Super Nanny");
|
||||
assertEquals(406, response.getStatus());
|
||||
|
@ -519,7 +561,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testWriteRuntimeIOException() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
PrintWriter writer = response.getWriter();
|
||||
writer.println("test");
|
||||
|
@ -546,7 +588,7 @@ public class ResponseTest
|
|||
public void testEncodeRedirect()
|
||||
throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
Request request = response.getHttpChannel().getRequest();
|
||||
request.setAuthority("myhost",8888);
|
||||
request.setContextPath("/path");
|
||||
|
@ -626,7 +668,7 @@ public class ResponseTest
|
|||
{
|
||||
for (int i=0;i<tests.length;i++)
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
Request request = response.getHttpChannel().getRequest();
|
||||
|
||||
request.setScheme("http");
|
||||
|
@ -660,7 +702,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testSetBufferSizeAfterHavingWrittenContent() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
response.setBufferSize(20 * 1024);
|
||||
response.getWriter().print("hello");
|
||||
try
|
||||
|
@ -677,7 +719,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testZeroContent() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
PrintWriter writer = response.getWriter();
|
||||
response.setContentLength(0);
|
||||
assertTrue(!response.isCommitted());
|
||||
|
@ -746,7 +788,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testAddCookie() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
Cookie cookie = new Cookie("name", "value");
|
||||
cookie.setDomain("domain");
|
||||
|
@ -765,7 +807,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testCookiesWithReset() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
|
||||
Cookie cookie=new Cookie("name","value");
|
||||
cookie.setDomain("domain");
|
||||
|
@ -800,7 +842,7 @@ public class ResponseTest
|
|||
@Test
|
||||
public void testFlushAfterFullContent() throws Exception
|
||||
{
|
||||
Response response = newResponse();
|
||||
Response response = getResponse();
|
||||
byte[] data = new byte[]{(byte)0xCA, (byte)0xFE};
|
||||
ServletOutputStream output = response.getOutputStream();
|
||||
response.setContentLength(data.length);
|
||||
|
@ -810,7 +852,6 @@ public class ResponseTest
|
|||
output.flush();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSetCookie() throws Exception
|
||||
{
|
||||
|
@ -927,14 +968,13 @@ public class ResponseTest
|
|||
response.addSetCookie("name","value%=",null,null,-1,null,false,false,0);
|
||||
setCookie=fields.get("Set-Cookie");
|
||||
assertEquals("name=value%=",setCookie);
|
||||
|
||||
}
|
||||
|
||||
private Response newResponse()
|
||||
private Response getResponse()
|
||||
{
|
||||
_channel.recycle();
|
||||
_channel.getRequest().setMetaData(new MetaData.Request("GET",new HttpURI("/path/info"),HttpVersion.HTTP_1_0,new HttpFields()));
|
||||
return new Response(_channel, _channel.getResponse().getHttpOutput());
|
||||
return _channel.getResponse();
|
||||
}
|
||||
|
||||
private static class TestSession extends Session
|
||||
|
|
|
@ -958,7 +958,7 @@ public class StartArgs
|
|||
if (arg.startsWith("--add-to-startd="))
|
||||
{
|
||||
String value = Props.getValue(arg);
|
||||
StartLog.warn("--add-to-startd is deprecated! Instead use:%n %s",value);
|
||||
StartLog.warn("--add-to-startd is deprecated! Instead use: --add-to-start=%s",value);
|
||||
createStartd=true;
|
||||
startModules.addAll(Props.getValues(arg));
|
||||
run = false;
|
||||
|
|
|
@ -36,10 +36,6 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* communications ability, but it does assist with query string
|
||||
* formatting.
|
||||
* </p>
|
||||
* <p>
|
||||
* UTF-8 encoding is used by default for % encoded characters. This
|
||||
* may be overridden with the org.eclipse.jetty.util.URI.charset system property.
|
||||
* </p>
|
||||
*
|
||||
* @see UrlEncoded
|
||||
*/
|
||||
|
|
|
@ -139,7 +139,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
// with a more automatic distributed mechanism
|
||||
public final static String[] __dftServerClasses =
|
||||
{
|
||||
"-org.eclipse.jetty.session.infinispan.", //don't hide infinispan support classes
|
||||
"-org.eclipse.jetty.server.session.SessionData", //don't hide SessionData for de/serialization purposes
|
||||
"-org.eclipse.jetty.jmx.", // don't hide jmx classes
|
||||
"-org.eclipse.jetty.util.annotation.", // don't hide jmx annotation
|
||||
"-org.eclipse.jetty.continuation.", // don't hide continuation classes
|
||||
|
|
Loading…
Reference in New Issue