Merge branch 'jetty-9.4.x' of github.com:eclipse/jetty.project into jetty-9.4.x

This commit is contained in:
Joakim Erdfelt 2016-08-05 11:44:17 -07:00
commit 1b3b57b2d3
26 changed files with 723 additions and 620 deletions

View File

@ -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

View File

@ -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>

View File

@ -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

View File

@ -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>
----

View File

@ -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].

View File

@ -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]

View File

@ -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);
}
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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));
}
}

View File

@ -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>

View File

@ -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");

View File

@ -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());

View File

@ -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;
}

View File

@ -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
{

View File

@ -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();
}
}
/**

View File

@ -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);

View File

@ -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;
}
}

View File

@ -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

View File

@ -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;

View File

@ -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
*/

View File

@ -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