Merge branch 'jetty-9.4.x' into 'jetty-9.4.x-websocket-sci-from-embedded'

This commit is contained in:
Joakim Erdfelt 2019-06-14 08:23:42 -05:00
commit 49ee5ac3c0
296 changed files with 4462 additions and 3216 deletions

View File

@ -1,10 +1,52 @@
jetty-9.4.19-SNAPSHOT
jetty-9.4.20-SNAPSHOT
jetty-9.4.19.v20190610 - 10 June 2019
+ 2909 Remove B64Code
+ 3332 jetty-maven-plugin - transitive dependencies not loaded from
"target/classes"
+ 3498 WebSocket Session.suspend() now suspends incoming frames instead
of reads
+ 3534 Use System nanoTime, not currentTimeMillis for IdleTimeout
+ 3550 Server becomes unresponsive after sitting idle from a load spike
+ 3562 InetAccessHandler should be able to apply to a certain port or
connector
+ 3568 Make UserStore able to be started/stopped with its LoginService
+ 3583 jetty-maven plugin in multi-module-project does not use files from
/target/test-classes folder of dependent projects
+ 3605 IdleTimeout with Jetty HTTP/2 and InputStreamResponseListener
+ 3608 Reply with 400 Bad request to malformed WebSocket handshake
+ 3616 Backport WebSocket SessionTracker from Jetty 10
+ 3620 Use of `throwUnavailableOnStartupException=true` does not stop Server
in jetty-home
+ 3627 Only renew session id when spnego authentication is fully complete
+ 3628 NPE in QueuedThreadPool.getReservedThreads()
+ 3630 X-Forwarded-For missing last hextet for ipv6
+ 3633 endpointIdentificationAlgorithm enabled by default
jetty-ssl-context.xml
+ 3653 access control exception if programmatic security manager is used
+ 3655 Spaces missing on Cookies generated via RFC6265
+ 3663 Remove deprecation of HttpClient replacement methods in WebSocketClient
+ 3680 Bom manages non-existent infinispan-remote and infinispan-embedded
dependencies due to config classifier
+ 3683 Multipart file not deleted when client aborts upload
+ 3690 Upgrade to asm 7.1
+ 3713 Emit warning when invoking deprecated method in Jetty XML
+ 3715 Improve Log.condensePackage performance
+ 3722 HttpSessionListener.sessionDestroyed should be able to access webapp
classes
+ 3726 Remove OSGi export uses of servlet-api from jetty-util
+ 3729 Make creation of java:comp/env threadsafe
+ 3743 Update XmlConfiguration usage in Jetty to always use Constructors that
provide Location information
+ 3748 @Resource field not injected in Jetty Demo
+ 3750 NPE in WebSocketClient.toString()
+ 3751 Modern Configure DTD / FPI is used inconsistently
jetty-9.4.18.v20190429 - 29 April 2019
+ 3476 IllegalStateException in WebSocket ConnectionState
+ 3550 Server becomes unresponsive after sitting idle from a load spike
+ 3563 Update to apache jasper 8.5.40
+ 3573 Update jetty-bom for new infinispan artifacts.
+ 3573 Update jetty-bom for new infinispan artifacts
+ 3582 HeapByteBuffer cleared unexpected
+ 3597 Session persistence broken from 9.4.13+
+ 3609 Fix infinispan start module dependencies

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apache-jsp</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>apache-jstl</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -24,7 +24,6 @@ import java.math.RoundingMode;
import java.net.URLEncoder;
import java.util.Map;
import java.util.Queue;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
@ -67,12 +66,25 @@ public class AbstractRestServlet extends HttpServlet
_appid = servletConfig.getInitParameter(APPID_PARAM);
}
public static String sanitize(String s)
// TODO: consider using StringUtil.sanitizeFileSystemName instead of this?
// might introduce jetty-util dependency though
public static String sanitize(String str)
{
if (s==null)
if (str == null)
return null;
return s.replace("<","?").replace("&","?").replace("\n","?");
char[] chars = str.toCharArray();
int len = chars.length;
for (int i = 0; i < len; i++)
{
char c = chars[i];
if ((c <= 0x1F) || // control characters
(c == '<') || (c == '&'))
{
chars[i] = '?';
}
}
return String.valueOf(chars);
}
protected String restURL(String item)

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>example-async-rest</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!--
This is the jetty specific web application configuration file. When starting

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.examples</groupId>
<artifactId>examples-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.examples</groupId>
<artifactId>examples-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -36,9 +36,8 @@ public class FileServerXml
{
public static void main( String[] args ) throws Exception
{
Resource fileserverXml = Resource.newSystemResource("fileserver.xml");
XmlConfiguration configuration = new XmlConfiguration(
fileserverXml.getInputStream());
Resource fileServerXml = Resource.newSystemResource("fileserver.xml");
XmlConfiguration configuration = new XmlConfiguration(fileServerXml);
Server server = (Server) configuration.configure();
server.start();
server.join();

View File

@ -24,7 +24,6 @@ import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.Date;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@ -158,7 +157,7 @@ public class Http2Server
public void destroy()
{
}
};
}
static Servlet servlet = new HttpServlet()
{

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-client</artifactId>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -6,7 +6,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-server</artifactId>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-alpn-parent</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-annotations</artifactId>

View File

@ -38,6 +38,8 @@ import org.eclipse.jetty.util.Loader;
import org.eclipse.jetty.util.ManifestUtils;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.MultiReleaseJarFile;
import org.eclipse.jetty.util.StringUtil;
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.resource.Resource;
@ -151,7 +153,7 @@ public class AnnotationParser
if (name.endsWith(".class"))
name = name.substring(0, name.length()-".class".length());
return name.replace('/', '.');
return StringUtil.replace(name,'/', '.');
}
/**
@ -599,13 +601,12 @@ public class AnnotationParser
if (className == null)
return;
String tmp = className;
className = className.replace('.', '/')+".class";
URL resource = Loader.getResource(className);
String classRef = TypeUtil.toClassReference(className);
URL resource = Loader.getResource(classRef);
if (resource!= null)
{
Resource r = Resource.newResource(resource);
addParsedClass(tmp, r);
addParsedClass(className, r);
try (InputStream is = r.getInputStream())
{
scanClass(handlers, null, is);
@ -626,7 +627,7 @@ public class AnnotationParser
Class<?> cz = clazz;
while (cz != Object.class)
{
String nameAsResource = cz.getName().replace('.', '/')+".class";
String nameAsResource = TypeUtil.toClassReference(cz);
URL resource = Loader.getResource(nameAsResource);
if (resource!= null)
{
@ -671,17 +672,16 @@ public class AnnotationParser
{
MultiException me = new MultiException();
for (String s:classNames)
for (String className : classNames)
{
try
{
String name = s;
s = s.replace('.', '/')+".class";
URL resource = Loader.getResource(s);
String classRef = TypeUtil.toClassReference(className);
URL resource = Loader.getResource(classRef);
if (resource!= null)
{
Resource r = Resource.newResource(resource);
addParsedClass(name, r);
addParsedClass(className, r);
try (InputStream is = r.getInputStream())
{
scanClass(handlers, null, is);
@ -690,7 +690,7 @@ public class AnnotationParser
}
catch (Exception e)
{
me.add(new RuntimeException("Error scanning class "+s, e));
me.add(new RuntimeException("Error scanning class "+className, e));
}
}
me.ifExceptionThrow();
@ -727,8 +727,9 @@ public class AnnotationParser
{
Path classpath = rootFile.toPath().relativize(file.toPath());
String str = classpath.toString();
str = str.substring(0, str.lastIndexOf(".class")).replace('/', '.').replace('\\', '.');
str = str.substring(0, str.lastIndexOf(".class"));
str = StringUtil.replace(str, File.separatorChar, '.');
try
{
if (LOG.isDebugEnabled())
@ -910,7 +911,7 @@ public class AnnotationParser
//check file is a valid class file name
if (isValidClassFileName(name) && isValidClassFilePath(name))
{
String shortName = name.replace('/', '.').substring(0,name.length()-6);
String shortName = StringUtil.replace(name, '/', '.').substring(0, name.length() - 6);
addParsedClass(shortName, Resource.newResource("jar:"+jar.getURI()+"!/"+entry.getNameInJar()));
if (LOG.isDebugEnabled())
LOG.debug("Scanning class from jar {}!/{}", jar, entry);

View File

@ -62,9 +62,7 @@ public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnno
//How to identify the correct Servlet? If the Servlet has no WebServlet annotation on it, does it mean that this MultipartConfig
//annotation applies to all declared instances in web.xml/programmatically?
//Assuming TRUE for now.
ServletHolder holder = getServletHolderForClass(clazz);
if (holder != null)
for (ServletHolder holder : _context.getServletHandler().getServlets(clazz))
{
Descriptor d = metaData.getOriginDescriptor(holder.getName()+".servlet.multipart-config");
//if a descriptor has already set the value for multipart config, do not
@ -76,21 +74,4 @@ public class MultiPartConfigAnnotationHandler extends AbstractIntrospectableAnno
}
}
}
private ServletHolder getServletHolderForClass (Class clazz)
{
ServletHolder holder = null;
ServletHolder[] holders = _context.getServletHandler().getServlets();
if (holders != null)
{
for (ServletHolder h : holders)
{
if (h.getClassName() != null && h.getClassName().equals(clazz.getName()))
{
holder = h;
}
}
}
return holder;
}
}

View File

@ -56,8 +56,7 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
String role = runAs.value();
if (role != null)
{
ServletHolder holder = getServletHolderForClass(clazz);
if (holder != null)
for (ServletHolder holder : _context.getServletHandler().getServlets(clazz))
{
MetaData metaData = _context.getMetaData();
Descriptor d = metaData.getOriginDescriptor(holder.getName()+".servlet.run-as");
@ -82,7 +81,6 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
else
LOG.warn("Bad value for @RunAs annotation on class "+clazz.getName());
}
}
public void handleField(String className, String fieldName, int access, String fieldType, String signature, Object value, String annotation)
@ -94,21 +92,4 @@ public class RunAsAnnotationHandler extends AbstractIntrospectableAnnotationHand
{
LOG.warn("@RunAs annotation ignored on method: "+className+"."+methodName+" "+signature);
}
private ServletHolder getServletHolderForClass (Class clazz)
{
ServletHolder holder = null;
ServletHolder[] holders = _context.getServletHandler().getServlets();
if (holders != null)
{
for (ServletHolder h : holders)
{
if (h.getClassName() != null && h.getClassName().equals(clazz.getName()))
{
holder = h;
}
}
}
return holder;
}
}

View File

@ -19,11 +19,12 @@
package org.eclipse.jetty.annotations;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
@ -42,6 +43,7 @@ import org.eclipse.jetty.toolchain.test.IO;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDir;
import org.eclipse.jetty.toolchain.test.jupiter.WorkDirExtension;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.resource.PathResource;
import org.eclipse.jetty.util.resource.Resource;
import org.junit.jupiter.api.Test;
@ -298,25 +300,17 @@ public class TestAnnotationParser
private void copyClass(Class<?> clazz, File basedir) throws IOException
{
String classname = clazz.getName().replace('.',File.separatorChar) + ".class";
URL url = this.getClass().getResource('/'+classname);
assertThat("URL for: " + classname,url,notNullValue());
String classRef = TypeUtil.toClassReference(clazz);
URL url = this.getClass().getResource('/' + classRef);
assertThat("URL for: " + classRef, url, notNullValue());
String classpath = classname.substring(0,classname.lastIndexOf(File.separatorChar));
FS.ensureDirExists(new File(basedir,classpath));
Path outputFile = basedir.toPath().resolve(classRef);
FS.ensureDirExists(outputFile.getParent());
InputStream in = null;
OutputStream out = null;
try
try (InputStream in = url.openStream();
OutputStream out = Files.newOutputStream(outputFile))
{
in = url.openStream();
out = new FileOutputStream(new File(basedir,classname));
IO.copy(in,out);
}
finally
{
IO.close(out);
IO.close(in);
IO.copy(in, out);
}
}
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-ant</artifactId>

View File

@ -28,6 +28,7 @@ import java.util.regex.Pattern;
import org.apache.tools.ant.AntClassLoader;
import org.eclipse.jetty.util.PatternMatcher;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
@ -88,7 +89,7 @@ public class AntWebInfConfiguration extends WebInfConfiguration
}
catch (URISyntaxException e)
{
containerUris[i] = new URI(u.toString().replaceAll(" ", "%20"));
containerUris[i] = new URI(URIUtil.encodeSpaces(u.toString()));
}
i++;
}

View File

@ -9,7 +9,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<build>
@ -53,341 +53,341 @@
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jsp</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>apache-jstl</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-client</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-java-client</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-java-server</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-openjdk8-client</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-openjdk8-server</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-conscrypt-client</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-conscrypt-server</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-alpn-server</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-annotations</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-ant</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>cdi-core</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>cdi-servlet</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-client</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-continuation</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-deploy</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-distribution</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-distribution</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
<type>tar.gz</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-client</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-server</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.gcloud</groupId>
<artifactId>jetty-gcloud-session-manager</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-home</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
<type>zip</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-home</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
<type>tar.gz</type>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-client</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-common</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-hpack</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-http-client-transport</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-server</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-http-spi</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>infinispan-common</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>infinispan-remote-query</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>infinispan-embedded-query</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-hazelcast</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-io</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jaas</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jaspi</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jmx</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jndi</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.memcached</groupId>
<artifactId>jetty-memcached-sessions</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-nosql</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot-jsp</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-osgi-boot-warurl</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.osgi</groupId>
<artifactId>jetty-httpservice</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-proxy</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-quickstart</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-rewrite</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-security</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlets</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-spring</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-unixsocket</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-util-ajax</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-client-impl</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>javax-websocket-server-impl</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-api</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-client</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-common</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-server</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.websocket</groupId>
<artifactId>websocket-servlet</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-xml</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</dependency>
</dependencies>
</dependencyManagement>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cdi-2</artifactId>

View File

@ -1,22 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.util.Decorator</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.util.DecoratedObjectFactory</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.server.handler.ContextHandler.</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.server.handler.ContextHandler</Arg>
</Call>
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.servlet.ServletContextHandler</Arg>
</Call>
<Get name="serverClasspathPattern">
<Call name="add">
<Arg>-org.eclipse.jetty.util.Decorator</Arg>
</Call>
<Call name="add">
<Arg>-org.eclipse.jetty.util.DecoratedObjectFactory</Arg>
</Call>
<Call name="add">
<Arg>-org.eclipse.jetty.server.handler.ContextHandler.</Arg>
</Call>
<Call name="add">
<Arg>-org.eclipse.jetty.server.handler.ContextHandler</Arg>
</Call>
<Call name="add">
<Arg>-org.eclipse.jetty.servlet.ServletContextHandler</Arg>
</Call>
</Get>
</Configure>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cdi-core</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cdi-full-servlet</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cdi-servlet</artifactId>

View File

@ -23,6 +23,7 @@ import javax.naming.Reference;
import org.eclipse.jetty.plus.jndi.Resource;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.webapp.ClasspathPattern;
import org.eclipse.jetty.webapp.WebAppContext;
/**
@ -45,22 +46,22 @@ public class JettyWeldInitializer
initContext(webapp);
// webapp cannot change / replace weld classes
webapp.addSystemClass("org.jboss.weld.");
webapp.addSystemClass("org.jboss.classfilewriter.");
webapp.addSystemClass("org.jboss.logging.");
webapp.addSystemClass("com.google.common.");
webapp.addSystemClass("org.eclipse.jetty.cdi.websocket.annotation.");
ClasspathPattern systemClasses = webapp.getSystemClasspathPattern();
systemClasses.add("org.jboss.weld.");
systemClasses.add("org.jboss.classfilewriter.");
systemClasses.add("org.jboss.logging.");
systemClasses.add("com.google.common.");
systemClasses.add("org.eclipse.jetty.cdi.websocket.annotation.");
// don't hide weld classes from webapps (allow webapp to use ones from system classloader)
webapp.prependServerClass("-org.eclipse.jetty.cdi.websocket.annotation.");
webapp.prependServerClass("-org.eclipse.jetty.cdi.core.");
webapp.prependServerClass("-org.eclipse.jetty.cdi.servlet.");
webapp.addServerClass("-org.jboss.weld.");
webapp.addServerClass("-org.jboss.classfilewriter.");
webapp.addServerClass("-org.jboss.logging.");
webapp.addServerClass("-com.google.common.");
ClasspathPattern serverClasses = webapp.getServerClasspathPattern();
serverClasses.add("-org.eclipse.jetty.cdi.websocket.annotation.");
serverClasses.add("-org.eclipse.jetty.cdi.core.");
serverClasses.add("-org.eclipse.jetty.cdi.servlet.");
serverClasses.add("-org.jboss.weld.");
serverClasses.add("-org.jboss.classfilewriter.");
serverClasses.add("-org.jboss.logging.");
serverClasses.add("-com.google.common.");
}
public static void initContext(ContextHandler handler) throws NamingException

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>cdi-websocket</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.cdi</groupId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.cdi</groupId>
<artifactId>jetty-cdi-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>test-cdi-webapp</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -22,12 +22,10 @@ import java.nio.ByteBuffer;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Supplier;
import org.eclipse.jetty.client.api.ContentProvider;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.util.BufferUtil;
@ -67,7 +65,6 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
private final AtomicReference<SenderState> senderState = new AtomicReference<>(SenderState.IDLE);
private final Callback commitCallback = new CommitCallback();
private final IteratingCallback contentCallback = new ContentCallback();
private final Callback trailersCallback = new TrailersCallback();
private final Callback lastCallback = new LastCallback();
private final HttpChannel channel;
private HttpContent content;
@ -444,15 +441,6 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
*/
protected abstract void sendContent(HttpExchange exchange, HttpContent content, Callback callback);
/**
* Implementations should send the HTTP trailers and notify the given {@code callback} of the
* result of this operation.
*
* @param exchange the exchange to send
* @param callback the callback to notify
*/
protected abstract void sendTrailers(HttpExchange exchange, Callback callback);
protected void reset()
{
HttpContent content = this.content;
@ -745,24 +733,14 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
if (content == null)
return;
HttpRequest request = exchange.getRequest();
Supplier<HttpFields> trailers = request.getTrailers();
boolean hasContent = content.hasContent();
if (!hasContent)
if (!content.hasContent())
{
if (trailers == null)
{
// No trailers or content to send, we are done.
someToSuccess(exchange);
}
else
{
sendTrailers(exchange, lastCallback);
}
// No content to send, we are done.
someToSuccess(exchange);
}
else
{
// Was any content sent while committing ?
// Was any content sent while committing?
ByteBuffer contentBuffer = content.getContent();
if (contentBuffer != null)
{
@ -859,9 +837,7 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
if (lastContent)
{
HttpRequest request = exchange.getRequest();
Supplier<HttpFields> trailers = request.getTrailers();
sendContent(exchange, content, trailers == null ? lastCallback : trailersCallback);
sendContent(exchange, content, lastCallback);
return Action.IDLE;
}
@ -925,28 +901,6 @@ public abstract class HttpSender implements AsyncContentProvider.Listener
}
}
private class TrailersCallback implements Callback
{
@Override
public void succeeded()
{
HttpExchange exchange = getHttpExchange();
if (exchange == null)
return;
sendTrailers(exchange, lastCallback);
}
@Override
public void failed(Throwable x)
{
HttpContent content = HttpSender.this.content;
if (content == null)
return;
content.failed(x);
anyToFailure(x);
}
}
private class LastCallback implements Callback
{
@Override

View File

@ -59,7 +59,7 @@ public class HttpSenderOverHTTP extends HttpSender
{
try
{
new HeadersCallback(exchange, content, callback, getHttpChannel().getHttpConnection()).iterate();
new HeadersCallback(exchange, content, callback).iterate();
}
catch (Throwable x)
{
@ -83,8 +83,8 @@ public class HttpSenderOverHTTP extends HttpSender
HttpGenerator.Result result = generator.generateRequest(null, null, chunk, contentBuffer, lastContent);
if (LOG.isDebugEnabled())
LOG.debug("Generated content ({} bytes) - {}/{}",
contentBuffer == null ? -1 : contentBuffer.remaining(),
result, generator);
contentBuffer == null ? -1 : contentBuffer.remaining(),
result, generator);
switch (result)
{
case NEED_CHUNK:
@ -94,8 +94,8 @@ public class HttpSenderOverHTTP extends HttpSender
}
case NEED_CHUNK_TRAILER:
{
callback.succeeded();
return;
chunk = bufferPool.acquire(httpClient.getRequestBufferSize(), false);
break;
}
case FLUSH:
{
@ -138,21 +138,6 @@ public class HttpSenderOverHTTP extends HttpSender
}
}
@Override
protected void sendTrailers(HttpExchange exchange, Callback callback)
{
try
{
new TrailersCallback(callback).iterate();
}
catch (Throwable x)
{
if (LOG.isDebugEnabled())
LOG.debug(x);
callback.failed(x);
}
}
@Override
protected void reset()
{
@ -191,19 +176,17 @@ public class HttpSenderOverHTTP extends HttpSender
private final HttpExchange exchange;
private final Callback callback;
private final MetaData.Request metaData;
private final HttpConnectionOverHTTP httpConnectionOverHTTP;
private ByteBuffer headerBuffer;
private ByteBuffer chunkBuffer;
private ByteBuffer contentBuffer;
private boolean lastContent;
private boolean generated;
public HeadersCallback(HttpExchange exchange, HttpContent content, Callback callback, HttpConnectionOverHTTP httpConnectionOverHTTP)
public HeadersCallback(HttpExchange exchange, HttpContent content, Callback callback)
{
super(false);
this.exchange = exchange;
this.callback = callback;
this.httpConnectionOverHTTP = httpConnectionOverHTTP;
HttpRequest request = exchange.getRequest();
ContentProvider requestContent = request.getContent();
@ -231,10 +214,10 @@ public class HttpSenderOverHTTP extends HttpSender
HttpGenerator.Result result = generator.generateRequest(metaData, headerBuffer, chunkBuffer, contentBuffer, lastContent);
if (LOG.isDebugEnabled())
LOG.debug("Generated headers ({} bytes), chunk ({} bytes), content ({} bytes) - {}/{}",
headerBuffer == null ? -1 : headerBuffer.remaining(),
chunkBuffer == null ? -1 : chunkBuffer.remaining(),
contentBuffer == null ? -1 : contentBuffer.remaining(),
result, generator);
headerBuffer == null ? -1 : headerBuffer.remaining(),
chunkBuffer == null ? -1 : chunkBuffer.remaining(),
contentBuffer == null ? -1 : contentBuffer.remaining(),
result, generator);
switch (result)
{
case NEED_HEADER:
@ -249,7 +232,8 @@ public class HttpSenderOverHTTP extends HttpSender
}
case NEED_CHUNK_TRAILER:
{
return Action.SUCCEEDED;
chunkBuffer = httpClient.getByteBufferPool().acquire(httpClient.getRequestBufferSize(), false);
break;
}
case FLUSH:
{
@ -260,11 +244,8 @@ public class HttpSenderOverHTTP extends HttpSender
chunkBuffer = BufferUtil.EMPTY_BUFFER;
if (contentBuffer == null)
contentBuffer = BufferUtil.EMPTY_BUFFER;
httpConnectionOverHTTP.addBytesOut( BufferUtil.length(headerBuffer)
+ BufferUtil.length(chunkBuffer)
+ BufferUtil.length(contentBuffer));
long bytes = headerBuffer.remaining() + chunkBuffer.remaining() + contentBuffer.remaining();
getHttpChannel().getHttpConnection().addBytesOut(bytes);
endPoint.write(this, headerBuffer, chunkBuffer, contentBuffer);
generated = true;
return Action.SCHEDULED;
@ -331,83 +312,6 @@ public class HttpSenderOverHTTP extends HttpSender
}
}
private class TrailersCallback extends IteratingCallback
{
private final Callback callback;
private ByteBuffer chunkBuffer;
public TrailersCallback(Callback callback)
{
this.callback = callback;
}
@Override
protected Action process() throws Throwable
{
while (true)
{
HttpGenerator.Result result = generator.generateRequest(null, null, chunkBuffer, null, true);
if (LOG.isDebugEnabled())
LOG.debug("Generated trailers {}/{}", result, generator);
switch (result)
{
case NEED_CHUNK_TRAILER:
{
chunkBuffer = httpClient.getByteBufferPool().acquire(httpClient.getRequestBufferSize(), false);
break;
}
case FLUSH:
{
EndPoint endPoint = getHttpChannel().getHttpConnection().getEndPoint();
endPoint.write(this, chunkBuffer);
return Action.SCHEDULED;
}
case SHUTDOWN_OUT:
{
shutdownOutput();
return Action.SUCCEEDED;
}
case DONE:
{
return Action.SUCCEEDED;
}
default:
{
throw new IllegalStateException(result.toString());
}
}
}
}
@Override
public void succeeded()
{
release();
super.succeeded();
}
@Override
public void failed(Throwable x)
{
release();
callback.failed(x);
super.failed(x);
}
@Override
protected void onCompleteSuccess()
{
super.onCompleteSuccess();
callback.succeeded();
}
private void release()
{
httpClient.getByteBufferPool().release(chunkBuffer);
chunkBuffer = null;
}
}
private class ByteBufferRecyclerCallback extends Callback.Nested
{
private final ByteBufferPool pool;
@ -435,7 +339,9 @@ public class HttpSenderOverHTTP extends HttpSender
public void failed(Throwable x)
{
for (ByteBuffer buffer : buffers)
{
pool.release(buffer);
}
super.failed(x);
}
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-deploy</artifactId>

View File

@ -91,7 +91,7 @@ public class GlobalWebappConfigBinding implements AppLifeCycle.Binding
if (globalContextSettings.exists())
{
XmlConfiguration jettyXmlConfig = new XmlConfiguration(globalContextSettings.getInputStream());
XmlConfiguration jettyXmlConfig = new XmlConfiguration(globalContextSettings);
Resource resource = Resource.newResource(app.getOriginId());
app.getDeploymentManager().scope(jettyXmlConfig,resource);
jettyXmlConfig.configure(context);

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/foo</Set>
<Set name="war">

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-distribution</artifactId>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<artifactId>jetty-documentation</artifactId>
<name>Jetty :: Documentation</name>

View File

@ -49,7 +49,7 @@ Copy and paste the following content as `$JETTY_BASE/webapps/jetty-wordpress.xml
[source, xml, subs="{sub-order}"]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.servlet.ServletContextHandler">
<New id="root" class="java.lang.String">

View File

@ -32,7 +32,8 @@ ____
This configuration is essentially the multiple logger configuration with added configuration to the deployers to force a `WebAppClassLoader` change to use the server classpath over the webapps classpath for the logger specific classes.
The technique used by this configuration is to provide an link:{JDURL}org/eclipse/jetty/deploy/AppLifeCycle.Binding.html[AppLifeCycle.Binding] against the link:{JDURL}/org/eclipse/jetty/deploy/AppLifeCycle.html[`"deploying"`node] that modifies the link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html#addSystemClass(java.lang.String)[WebAppContext.addSystemClass(String)] for the common logging classes.
The technique used by this configuration is to provide an link:{JDURL}org/eclipse/jetty/deploy/AppLifeCycle.Binding.html[AppLifeCycle.Binding] against the link:{JDURL}/org/eclipse/jetty/deploy/AppLifeCycle.html[`"deploying"`node] that modifies the
link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html#getSystemClasspathPattern()[WebAppContext.getSystemClasspathPattern().add(String)] for the common logging classes.
See https://github.com/jetty-project/jetty-webapp-logging/blob/master/src/main/java/org/eclipse/jetty/webapp/logging/CentralizedWebAppLoggingBinding.java[org.eclipse.jetty.logging.CentralizedWebAppLoggingBinding] for actual implementation.
A convenient replacement `logging` module has been created to bootstrap your `${jetty.base}` directory for capturing all Jetty server logging from multiple logging frameworks into a single logging output file managed by Logback.

View File

@ -94,9 +94,11 @@ From a context xml file, you reference the Server instance as a Ref:
[source, xml, subs="{sub-order}"]
----
<!-- Expose the jetty infinispan classes for session serialization -->
<Call name="prependServerClass">
<Arg>-org.eclipse.jetty.session.infinispan.</Arg>
</Call>
<Get name="serverClasspathPattern">
<Call name="add">
<Arg>-org.eclipse.jetty.session.infinispan.</Arg>
</Call>
</Get>
<!-- Get a reference to the InfinispanSessionIdManager -->
@ -132,10 +134,12 @@ From a `WEB-INF/jetty-web.xml` file, you can reference the Server instance direc
[source, xml, subs="{sub-order}"]
----
<!-- Expose the jetty infinispan classes for session serialization -->
<Call name="prependServerClass">
<!-- Expose the jetty infinispan classes for session serialization -->
<Get name="serverClasspathPattern">
<Call name="add">
<Arg>-org.eclipse.jetty.session.infinispan.</Arg>
</Call>
</Get>
<!-- Reference the server directly -->
<Get name="server">
@ -143,25 +147,25 @@ From a `WEB-INF/jetty-web.xml` file, you can reference the Server instance direc
</Get>
<!-- Get a reference to the Cache via the InfinispanSessionIdManager -->
<Ref id="idMgr">
<Get id="cache" name="cache"/>
</Ref>
<Ref id="idMgr">
<Get id="cache" name="cache"/>
</Ref>
<!-- Apply the SessionIdManager and Cache to the InfinispanSessionManager -->
<Set name="sessionHandler">
<New class="org.eclipse.jetty.server.session.SessionHandler">
<Arg>
<New id="mgr" class="org.eclipse.jetty.session.infinispan.InfinispanSessionManager">
<Set name="sessionIdManager">
<Ref id="idMgr"/>
</Set>
<Set name="cache">
<Ref id="cache">
</Ref>
</Set>
<Set name="scavengeInterval">600</Set>
</New>
</Arg>
<Arg>
<New id="mgr" class="org.eclipse.jetty.session.infinispan.InfinispanSessionManager">
<Set name="sessionIdManager">
<Ref id="idMgr"/>
</Set>
<Set name="cache">
<Ref id="cache">
</Ref>
</Set>
<Set name="scavengeInterval">600</Set>
</New>
</Arg>
</New>
</Set>
----
@ -178,7 +182,7 @@ staleIntervalSec::
===== Using HotRod
If you're using the hotrod client - where serialization will be required - you will need to ensure that the hotrod marshalling software works with Jetty classloading.
To do this, firstly ensure that you have included the lines containing the `prependServerClass` to your context xml file as shown above.
To do this, firstly ensure that you have included the lines containing the `getServerClasspathPattern().add(...)` to your context xml file as shown above.
Then, create the file `${jetty.base}/resources/hotrod-client.properties`.
Add the following line to this file:

View File

@ -77,7 +77,7 @@ Context files are normally located in `${jetty.base}/webapps/` (see `DeployerMan
[source, xml, subs="{sub-order}"]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.eclipse.org/configure.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/test</Set>

View File

@ -79,7 +79,11 @@ Below is an example of implementing this feature using Jetty IoC XML format:
[[classloading-setting-system-classes]]
===== Setting System Classes
You can call the methods link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html#setSystemClasses%28java.lang.String%5B%5D%29[org.eclipse.jetty.webapp.WebAppContext.setSystemClasses(String Array)] or link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html#addSystemClass(java.lang.String)[org.eclipse.jetty.webapp.WebAppContext.addSystemClass(String)] to allow fine control over which classes are considered System classes.
You can call the methods
link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html#setSystemClasses%28java.lang.String%5B%5D%29[WebAppContext.setSystemClasses(String[\])]
or
link:{JDURL}/org/eclipse/jetty/webapp/WebAppContext.html#getSystemClasspathPattern()[WebAppContext.getSystemClasspathPattern().add(String)]
to allow fine control over which classes are considered system classes.
* A web application can see a System class.
* A WEB-INF class cannot replace a System class.

View File

@ -34,7 +34,7 @@ Jetty applies `jetty-env.xml` on a per-webapp basis, and configures an instance
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
..
@ -57,7 +57,7 @@ Place the `jetty-env.xml` file in your web application's WEB-INF folder.
----
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://jetty.mortbay.org/configure.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">

View File

@ -33,7 +33,7 @@ For a more in-depth look at the syntax, see xref:jetty-xml-syntax[].
[source, xml, subs="{sub-order}"]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
..

View File

@ -43,7 +43,7 @@ The selection of which configuration files to use is controlled by `start.jar` a
----
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
...

View File

@ -34,7 +34,7 @@ The following XML configuration file creates some Java objects and sets some att
[source, xml, subs="{sub-order}"]
----
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure id="foo" class="com.acme.Foo">
<Set name="name">demo</Set>
<Set name="nested">
@ -89,13 +89,13 @@ The first two lines of an XML must reference the DTD to be used to validate the
[source, xml, subs="{sub-order}"]
----
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
...
----
Typcically a good XML editor will fetch the DTD from the URL and use it to give syntax highlighting and validation while a configuration file is being edited.
Some editors also allows DTD files to be locally cached.
The URL may point to configure.dtd if you want the latest current version, or to a specific version like configure_9_0.dtd if you want a particular validation feature set.
The URL may point to configure.dtd if you want the latest current version, or to a specific version like configure_9_3.dtd if you want a particular validation feature set.
Files that conform to the configure.dtd format are processed in Jetty by the `XmlConfiguration` class which may also validate the XML (using a version of the DTD from the classes jar file), but is by default run in a forgiving mode that tries to work around validation failures.

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -35,6 +35,7 @@ import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.Jetty;
import org.eclipse.jetty.util.StringUtil;
public class HttpSenderOverFCGI extends HttpSender
{
@ -88,7 +89,7 @@ public class HttpSenderOverFCGI extends HttpSender
for (HttpField field : headers)
{
String name = field.getName();
String fcgiName = "HTTP_" + name.replaceAll("-", "_").toUpperCase(Locale.ENGLISH);
String fcgiName = "HTTP_" + StringUtil.replace(name, '-', '_').toUpperCase(Locale.ENGLISH);
fcgiHeaders.add(fcgiName, field.getValue());
}
@ -125,10 +126,4 @@ public class HttpSenderOverFCGI extends HttpSender
getHttpChannel().flush(result);
}
}
@Override
protected void sendTrailers(HttpExchange exchange, Callback callback)
{
callback.succeeded();
}
}

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.fcgi</groupId>
<artifactId>fcgi-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -24,7 +24,6 @@ import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
@ -35,6 +34,8 @@ import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.util.StringUtil;
/**
* Inspired by nginx's try_files functionality.
* <p>
@ -132,7 +133,7 @@ public class TryFilesFilter implements Filter
path += info;
if (!path.startsWith("/"))
path = "/" + path;
return value.replaceAll("\\$path", path);
return StringUtil.replace(value, "$path", path);
}
@Override

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -5,7 +5,7 @@
<parent>
<groupId>org.eclipse.jetty.gcloud</groupId>
<artifactId>gcloud-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-home</artifactId>

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!-- ================================================================ -->
<!-- Configure the Jetty SetUIDListener -->

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http-spi</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-http</artifactId>

View File

@ -276,12 +276,9 @@ public class HttpField
public boolean isSameName(HttpField field)
{
@SuppressWarnings("ReferenceEquality")
boolean sameObject = (field==this);
if (field==null)
return false;
if (sameObject)
if (field==this)
return true;
if (_header!=null && _header==field.getHeader())
return true;

View File

@ -33,7 +33,6 @@ import java.util.Set;
import java.util.StringTokenizer;
import java.util.function.ToIntFunction;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.eclipse.jetty.util.ArrayTernaryTrie;
import org.eclipse.jetty.util.QuotedStringTokenizer;
@ -47,7 +46,7 @@ import org.eclipse.jetty.util.log.Logger;
*
* <p>This class is not synchronized as it is expected that modifications will only be performed by a
* single thread.
*
*
* <p>The cookie handling provided by this class is guided by the Servlet specification and RFC6265.
*
*/
@ -60,33 +59,33 @@ public class HttpFields implements Iterable<HttpField>
private HttpField[] _fields;
private int _size;
/**
* Initialize an empty HttpFields.
*/
public HttpFields()
{
_fields=new HttpField[20];
this(16); // Based on small sample of Chrome requests.
}
/**
* Initialize an empty HttpFields.
*
*
* @param capacity the capacity of the http fields
*/
public HttpFields(int capacity)
{
_fields=new HttpField[capacity];
}
/**
* Initialize HttpFields from copy.
*
*
* @param fields the fields to copy data from
*/
public HttpFields(HttpFields fields)
{
_fields=Arrays.copyOf(fields._fields,fields._fields.length+10);
_fields=Arrays.copyOf(fields._fields,fields._fields.length);
_size=fields._size;
}
@ -94,22 +93,22 @@ public class HttpFields implements Iterable<HttpField>
{
return _size;
}
@Override
public Iterator<HttpField> iterator()
{
return new Itr();
return new ListItr();
}
public ListIterator<HttpField> listIterator()
{
return new Itr();
return new ListItr();
}
public Stream<HttpField> stream()
{
return StreamSupport.stream(Arrays.spliterator(_fields,0,_size),false);
return Arrays.stream(_fields).limit(_size);
}
/**
@ -118,13 +117,15 @@ public class HttpFields implements Iterable<HttpField>
*/
public Set<String> getFieldNamesCollection()
{
final Set<String> set = new HashSet<>(_size);
for (HttpField f : this)
Set<String> set = null;
for (int i=0;i<_size;i++)
{
if (f!=null)
set.add(f.getName());
HttpField f=_fields[i];
if (set==null)
set = new HashSet<>();
set.add(f.getName());
}
return set;
return set==null?Collections.emptySet():set;
}
/**
@ -139,7 +140,7 @@ public class HttpFields implements Iterable<HttpField>
/**
* Get a Field by index.
* @param index the field index
* @param index the field index
* @return A Field value or null if the Field value has not been set
*/
public HttpField getField(int index)
@ -171,6 +172,22 @@ public class HttpFields implements Iterable<HttpField>
return null;
}
public List<HttpField> getFields(HttpHeader header)
{
List<HttpField> fields = null;
for (int i=0;i<_size;i++)
{
HttpField f=_fields[i];
if (f.getHeader()==header)
{
if (fields==null)
fields = new ArrayList<>();
fields.add(f);
}
}
return fields==null?Collections.emptyList():fields;
}
public boolean contains(HttpField field)
{
for (int i=_size;i-->0;)
@ -192,7 +209,7 @@ public class HttpFields implements Iterable<HttpField>
}
return false;
}
public boolean contains(String name, String value)
{
for (int i=_size;i-->0;)
@ -214,7 +231,7 @@ public class HttpFields implements Iterable<HttpField>
}
return false;
}
public boolean containsKey(String name)
{
for (int i=_size;i-->0;)
@ -231,7 +248,7 @@ public class HttpFields implements Iterable<HttpField>
{
return get(header);
}
public String get(HttpHeader header)
{
for (int i=0;i<_size;i++)
@ -248,7 +265,7 @@ public class HttpFields implements Iterable<HttpField>
{
return get(name);
}
public String get(String header)
{
for (int i=0;i<_size;i++)
@ -269,24 +286,30 @@ public class HttpFields implements Iterable<HttpField>
public List<String> getValuesList(HttpHeader header)
{
final List<String> list = new ArrayList<>();
for (HttpField f : this)
if (f.getHeader()==header)
for (int i=0;i<_size;i++)
{
HttpField f = _fields[i];
if (f.getHeader() == header)
list.add(f.getValue());
}
return list;
}
/**
* Get multiple header of the same name
*
*
* @return List the header values
* @param name the case-insensitive field name
*/
public List<String> getValuesList(String name)
{
final List<String> list = new ArrayList<>();
for (HttpField f : this)
for (int i=0;i<_size;i++)
{
HttpField f = _fields[i];
if (f.getName().equalsIgnoreCase(name))
list.add(f.getValue());
}
return list;
}
@ -301,8 +324,9 @@ public class HttpFields implements Iterable<HttpField>
public boolean addCSV(HttpHeader header,String... values)
{
QuotedCSV existing = null;
for (HttpField f : this)
for (int i=0;i<_size;i++)
{
HttpField f = _fields[i];
if (f.getHeader()==header)
{
if (existing==null)
@ -310,7 +334,7 @@ public class HttpFields implements Iterable<HttpField>
existing.addValue(f.getValue());
}
}
String value = addCSV(existing,values);
if (value!=null)
{
@ -319,7 +343,7 @@ public class HttpFields implements Iterable<HttpField>
}
return false;
}
/**
* Add comma separated values, but only if not already
* present.
@ -330,8 +354,9 @@ public class HttpFields implements Iterable<HttpField>
public boolean addCSV(String name,String... values)
{
QuotedCSV existing = null;
for (HttpField f : this)
for (int i=0;i<_size;i++)
{
HttpField f = _fields[i];
if (f.getName().equalsIgnoreCase(name))
{
if (existing==null)
@ -348,14 +373,14 @@ public class HttpFields implements Iterable<HttpField>
return false;
}
protected String addCSV(QuotedCSV existing,String... values)
protected String addCSV(QuotedCSV existing, String... values)
{
// remove any existing values from the new values
boolean add = true;
if (existing!=null && !existing.isEmpty())
{
add = false;
for (int i=values.length;i-->0;)
{
String unquoted = QuotedCSV.unquote(values[i]);
@ -365,7 +390,7 @@ public class HttpFields implements Iterable<HttpField>
add = true;
}
}
if (add)
{
StringBuilder value = new StringBuilder();
@ -380,12 +405,12 @@ public class HttpFields implements Iterable<HttpField>
if (value.length()>0)
return value.toString();
}
return null;
}
/**
* Get multiple field values of the same name, split
* Get multiple field values of the same name, split
* as a {@link QuotedCSV}
*
* @return List the values with OWS stripped
@ -499,7 +524,7 @@ public class HttpFields implements Iterable<HttpField>
for (int i=0;i<_size;i++)
{
final HttpField f = _fields[i];
if (f.getName().equalsIgnoreCase(name) && f.getValue()!=null)
{
final int first=i;
@ -513,7 +538,7 @@ public class HttpFields implements Iterable<HttpField>
{
if (field==null)
{
while (i<_size)
while (i<_size)
{
field=_fields[i++];
if (field.getName().equalsIgnoreCase(name) && field.getValue()!=null)
@ -613,7 +638,7 @@ public class HttpFields implements Iterable<HttpField>
if (!put)
add(field);
}
/**
* Set a field.
*
@ -905,7 +930,7 @@ public class HttpFields implements Iterable<HttpField>
{
_size=0;
}
public void add(HttpField field)
{
if (field!=null)
@ -1083,37 +1108,36 @@ public class HttpFields implements Iterable<HttpField>
return values.getValues();
}
private class Itr implements ListIterator<HttpField>
private class ListItr implements ListIterator<HttpField>
{
int _cursor; // index of next element to return
int _last=-1;
int _current =-1;
@Override
public boolean hasNext()
public boolean hasNext()
{
return _cursor != _size;
}
@Override
public HttpField next()
public HttpField next()
{
int i = _cursor;
if (i >= _size)
if (_cursor == _size)
throw new NoSuchElementException();
_cursor = i + 1;
return _fields[_last=i];
_current = _cursor++;
return _fields[_current];
}
@Override
public void remove()
public void remove()
{
if (_last<0)
if (_current <0)
throw new IllegalStateException();
System.arraycopy(_fields,_last+1,_fields,_last,--_size-_last);
_cursor=_last;
_last=-1;
_size--;
System.arraycopy(_fields, _current +1,_fields, _current,_size- _current);
_fields[_size]=null;
_cursor= _current;
_current =-1;
}
@Override
@ -1127,7 +1151,8 @@ public class HttpFields implements Iterable<HttpField>
{
if (_cursor == 0)
throw new NoSuchElementException();
return _fields[_last=--_cursor];
_current = --_cursor;
return _fields[_current];
}
@Override
@ -1144,10 +1169,10 @@ public class HttpFields implements Iterable<HttpField>
@Override
public void set(HttpField field)
{
if (_last<0)
{
if (_current <0)
throw new IllegalStateException();
_fields[_last] = field;
_fields[_current] = field;
}
@Override
@ -1156,8 +1181,7 @@ public class HttpFields implements Iterable<HttpField>
_fields = Arrays.copyOf(_fields,_fields.length+1);
System.arraycopy(_fields,_cursor,_fields,_cursor+1,_size++);
_fields[_cursor++] = field;
_last=-1;
_current =-1;
}
}
}

View File

@ -196,7 +196,7 @@ public class MimeTypes
int charset=type.toString().indexOf(";charset=");
if (charset>0)
{
String alt=type.toString().replace(";charset=","; charset=");
String alt = StringUtil.replace(type.toString(), ";charset=", "; charset=");
CACHE.put(alt,type);
TYPES.put(alt,type.asBuffer());
}

View File

@ -35,7 +35,6 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import javax.servlet.MultipartConfigElement;
import javax.servlet.ServletInputStream;
import javax.servlet.http.Part;
@ -299,9 +298,8 @@ public class MultiPartFormInputStream
*/
public void cleanUp() throws IOException
{
if (_temporary && _file != null && _file.exists())
if (!_file.delete())
throw new IOException("Could Not Delete File");
if (_temporary)
delete();
}
/**
@ -398,31 +396,21 @@ public class MultiPartFormInputStream
*/
public void deleteParts()
{
if (!_parsed)
return;
Collection<Part> parts;
try
{
parts = getParts();
}
catch (IOException e)
{
throw new RuntimeException(e);
}
MultiException err = null;
for (Part p : parts)
for (List<Part> parts : _parts.values())
{
try
for (Part p : parts)
{
((MultiPart)p).cleanUp();
}
catch (Exception e)
{
if (err == null)
err = new MultiException();
err.add(e);
try
{
((MultiPart)p).cleanUp();
}
catch (Exception e)
{
if (err == null)
err = new MultiException();
err.add(e);
}
}
}
_parts.clear();
@ -477,6 +465,9 @@ public class MultiPartFormInputStream
{
if (_err != null)
{
if (LOG.isDebugEnabled())
LOG.debug("MultiPart parsing failure ", _err);
_err.addSuppressed(new Throwable());
if (_err instanceof IOException)
throw (IOException)_err;
@ -495,7 +486,9 @@ public class MultiPartFormInputStream
if (_parsed)
return;
_parsed = true;
MultiPartParser parser = null;
Handler handler = new Handler();
try
{
// initialize
@ -531,9 +524,7 @@ public class MultiPartFormInputStream
contentTypeBoundary = QuotedStringTokenizer.unquote(value(_contentType.substring(bstart, bend)).trim());
}
Handler handler = new Handler();
MultiPartParser parser = new MultiPartParser(handler, contentTypeBoundary);
parser = new MultiPartParser(handler, contentTypeBoundary);
byte[] data = new byte[_bufferSize];
int len;
long total = 0;
@ -545,7 +536,6 @@ public class MultiPartFormInputStream
if (len > 0)
{
// keep running total of size of bytes read from input and throw an exception if exceeds MultipartConfigElement._maxRequestSize
total += len;
if (_config.getMaxRequestSize() > 0 && total > _config.getMaxRequestSize())
@ -595,6 +585,10 @@ public class MultiPartFormInputStream
catch (Throwable e)
{
_err = e;
// Notify parser if failure occurs
if (parser != null)
parser.parse(BufferUtil.EMPTY_BUFFER, true);
}
}
@ -742,6 +736,16 @@ public class MultiPartFormInputStream
{
if (LOG.isDebugEnabled())
LOG.debug("Early EOF {}", MultiPartFormInputStream.this);
try
{
if (_part != null)
_part.close();
}
catch (IOException e)
{
LOG.warn("part could not be closed", e);
}
}
public void reset()

View File

@ -131,12 +131,8 @@ public class MultiPartParser
private HttpTokens.Token next(ByteBuffer buffer)
{
byte ch = buffer.get();
HttpTokens.Token t = HttpTokens.TOKENS[0xff & ch];
if (DEBUG)
LOG.debug("token={}",t);
switch(t.getType())
{
case CNTL:
@ -271,6 +267,9 @@ public class MultiPartParser
/* ------------------------------------------------------------------------------- */
private void parsePreamble(ByteBuffer buffer)
{
if (LOG.isDebugEnabled())
LOG.debug("parsePreamble({})", BufferUtil.toDetailString(buffer));
if (_partialBoundary > 0)
{
int partial = _delimiterSearch.startsWith(buffer.array(), buffer.arrayOffset() + buffer.position(), buffer.remaining(), _partialBoundary);
@ -307,6 +306,9 @@ public class MultiPartParser
/* ------------------------------------------------------------------------------- */
private void parseDelimiter(ByteBuffer buffer)
{
if (LOG.isDebugEnabled())
LOG.debug("parseDelimiter({})", BufferUtil.toDetailString(buffer));
while (__delimiterStates.contains(_state) && hasNextByte(buffer))
{
HttpTokens.Token t = next(buffer);
@ -354,6 +356,9 @@ public class MultiPartParser
*/
protected boolean parseMimePartHeaders(ByteBuffer buffer)
{
if (LOG.isDebugEnabled())
LOG.debug("parseMimePartHeaders({})", BufferUtil.toDetailString(buffer));
// Process headers
while (_state == State.BODY_PART && hasNextByte(buffer))
{
@ -575,6 +580,8 @@ public class MultiPartParser
protected boolean parseOctetContent(ByteBuffer buffer)
{
if (LOG.isDebugEnabled())
LOG.debug("parseOctetContent({})", BufferUtil.toDetailString(buffer));
// Starts With
if (_partialBoundary > 0)

View File

@ -217,6 +217,7 @@ public class MultiPartFormInputStreamTest
@Test
public void testNoBody()
throws Exception
{
String body = "";
@ -277,6 +278,7 @@ public class MultiPartFormInputStreamTest
@Test
public void testWhitespaceBodyWithCRLF()
throws Exception
{
String whitespace = " \n\n\n\r\n\r\n\r\n\r\n";
@ -292,6 +294,7 @@ public class MultiPartFormInputStreamTest
@Test
public void testWhitespaceBody()
throws Exception
{
String whitespace = " ";
@ -400,6 +403,7 @@ public class MultiPartFormInputStreamTest
@Test
public void testRequestTooBig ()
throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 60, 100, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(_multi.getBytes()),
@ -415,6 +419,7 @@ public class MultiPartFormInputStreamTest
@Test
public void testRequestTooBigThrowsErrorOnGetParts ()
throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 60, 100, 50);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(_multi.getBytes()),
@ -434,6 +439,7 @@ public class MultiPartFormInputStreamTest
@Test
public void testFileTooBig()
throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 40, 1024, 30);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(_multi.getBytes()),
@ -449,6 +455,7 @@ public class MultiPartFormInputStreamTest
@Test
public void testFileTooBigThrowsErrorOnGetParts()
throws Exception
{
MultipartConfigElement config = new MultipartConfigElement(_dirname, 40, 1024, 30);
MultiPartFormInputStream mpis = new MultiPartFormInputStream(new ByteArrayInputStream(_multi.getBytes()),
@ -550,6 +557,7 @@ public class MultiPartFormInputStreamTest
@Test
public void testCROnlyRequest()
throws Exception
{
String str = "--AaB03x\r" +
"content-disposition: form-data; name=\"field1\"\r" +
@ -576,6 +584,7 @@ public class MultiPartFormInputStreamTest
@Test
public void testCRandLFMixRequest()
throws Exception
{
String str = "--AaB03x\r" +
"content-disposition: form-data; name=\"field1\"\r" +

View File

@ -18,13 +18,13 @@
package org.eclipse.jetty.http;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import org.eclipse.jetty.util.StringUtil;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.is;
public class QuotedCSVTest
{
@Test
@ -111,13 +111,13 @@ public class QuotedCSVTest
{
if (buffer.toString().contains("DELETE"))
{
String s = buffer.toString().replace("DELETE","");
String s = StringUtil.strip(buffer.toString(), "DELETE");
buffer.setLength(0);
buffer.append(s);
}
if (buffer.toString().contains("APPEND"))
{
String s = buffer.toString().replace("APPEND","Append")+"!";
String s = StringUtil.replace(buffer.toString(), "APPEND", "Append") + "!";
buffer.setLength(0);
buffer.append(s);
}

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -48,6 +48,7 @@ import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
@ -167,7 +168,7 @@ public class ProxyProtocolTest
// String is: "MAGIC VER|CMD FAM|PROT LEN SRC_ADDR DST_ADDR SRC_PORT DST_PORT PP2_TYPE_SSL LEN CLIENT VERIFY PP2_SUBTYPE_SSL_VERSION LEN 1.2"
String request1 = "0D0A0D0A000D0A515549540A 21 11 001A 0A000004 0A000005 8420 22B8 20 000B 01 00000000 21 0003 312E32";
request1 = request1.replace(" ", "");
request1 = StringUtil.strip(request1, " ");
SocketChannel channel = SocketChannel.open();
channel.connect(new InetSocketAddress("localhost", connector.getLocalPort()));
channel.write(ByteBuffer.wrap(TypeUtil.fromHexString(request1)));

View File

@ -18,16 +18,6 @@
package org.eclipse.jetty.http2.client;
import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
@ -35,7 +25,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@ -58,10 +47,14 @@ import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FuturePromise;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.StringUtil;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class TrailersTest extends AbstractTest
{
@ -289,7 +282,7 @@ public class TrailersTest extends AbstractTest
assertTrue(latch.await(5, TimeUnit.SECONDS));
assertTrue( frames.size()==3, frames.toString());
assertEquals(3, frames.size(), frames.toString());
HeadersFrame headers = (HeadersFrame)frames.get(0);
DataFrame data = (DataFrame)frames.get(1);
@ -298,7 +291,7 @@ public class TrailersTest extends AbstractTest
assertFalse(headers.isEndStream());
assertFalse(data.isEndStream());
assertTrue(trailers.isEndStream());
assertTrue(trailers.getMetaData().getFields().get(trailerName).equals(trailerValue));
assertEquals(trailers.getMetaData().getFields().get(trailerName), trailerValue);
}
@Test
@ -358,6 +351,5 @@ public class TrailersTest extends AbstractTest
assertTrue(serverLatch.await(5, TimeUnit.SECONDS));
assertTrue(clientLatch.await(5, TimeUnit.SECONDS));
}
}

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -39,7 +39,7 @@ public class MetaDataBuilder
private HostPortHttpField _authority;
private String _path;
private long _contentLength=Long.MIN_VALUE;
private HttpFields _fields = new HttpFields(10);
private HttpFields _fields = new HttpFields();
private HpackException.StreamException _streamException;
private boolean _request;
private boolean _response;
@ -255,7 +255,7 @@ public class MetaDataBuilder
}
finally
{
_fields = new HttpFields(Math.max(10, fields.size() + 5));
_fields = new HttpFields(Math.max(16, fields.size() + 5));
_request = false;
_response = false;
_status = null;

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -56,42 +56,57 @@ public class HttpSenderOverHTTP2 extends HttpSender
String path = relativize(request.getPath());
HttpURI uri = HttpURI.createHttpURI(request.getScheme(), request.getHost(), request.getPort(), path, null, request.getQuery(), null);
MetaData.Request metaData = new MetaData.Request(request.getMethod(), uri, HttpVersion.HTTP_2, request.getHeaders());
Supplier<HttpFields> trailers = request.getTrailers();
metaData.setTrailerSupplier(trailers);
HeadersFrame headersFrame = new HeadersFrame(metaData, null, trailers == null && !content.hasContent());
HttpChannelOverHTTP2 channel = getHttpChannel();
Promise<Stream> promise = new Promise<Stream>()
{
@Override
public void succeeded(Stream stream)
{
channel.setStream(stream);
((IStream)stream).setAttachment(channel);
long idleTimeout = request.getIdleTimeout();
if (idleTimeout >= 0)
stream.setIdleTimeout(idleTimeout);
Supplier<HttpFields> trailerSupplier = request.getTrailers();
metaData.setTrailerSupplier(trailerSupplier);
if (content.hasContent() && !expects100Continue(request))
HeadersFrame headersFrame;
Promise<Stream> promise;
if (content.hasContent())
{
headersFrame = new HeadersFrame(metaData, null, false);
promise = new HeadersPromise(request, callback)
{
@Override
public void succeeded(Stream stream)
{
boolean advanced = content.advance();
boolean lastContent = trailers == null && content.isLast();
if (advanced || lastContent)
super.succeeded(stream);
if (expects100Continue(request))
{
DataFrame dataFrame = new DataFrame(stream.getId(), content.getByteBuffer(), lastContent);
stream.data(dataFrame, callback);
return;
// Don't send the content yet.
callback.succeeded();
}
else
{
boolean advanced = content.advance();
boolean lastContent = content.isLast();
if (advanced || lastContent)
sendContent(stream, content, trailerSupplier, callback);
else
callback.succeeded();
}
}
callback.succeeded();
}
@Override
public void failed(Throwable failure)
};
}
else
{
HttpFields trailers = trailerSupplier == null ? null : trailerSupplier.get();
boolean endStream = trailers == null || trailers.size() == 0;
headersFrame = new HeadersFrame(metaData, null, endStream);
promise = new HeadersPromise(request, callback)
{
callback.failed(failure);
}
};
@Override
public void succeeded(Stream stream)
{
super.succeeded(stream);
if (endStream)
callback.succeeded();
else
sendTrailers(stream, trailers, callback);
}
};
}
// TODO optimize the send of HEADERS and DATA frames.
HttpChannelOverHTTP2 channel = getHttpChannel();
channel.getSession().newStream(headersFrame, promise, channel.getStreamListener());
}
@ -118,24 +133,67 @@ public class HttpSenderOverHTTP2 extends HttpSender
{
if (content.isConsumed())
{
// The superclass calls sendContent() one more time after the last content.
// This is necessary for HTTP/1.1 to generate the terminal chunk (with trailers),
// but it's not necessary for HTTP/2 so we just succeed the callback.
callback.succeeded();
}
else
{
Stream stream = getHttpChannel().getStream();
Supplier<HttpFields> trailers = exchange.getRequest().getTrailers();
DataFrame frame = new DataFrame(stream.getId(), content.getByteBuffer(), trailers == null && content.isLast());
stream.data(frame, callback);
Supplier<HttpFields> trailerSupplier = exchange.getRequest().getTrailers();
sendContent(stream, content, trailerSupplier, callback);
}
}
@Override
protected void sendTrailers(HttpExchange exchange, Callback callback)
private void sendContent(Stream stream, HttpContent content, Supplier<HttpFields> trailerSupplier, Callback callback)
{
Supplier<HttpFields> trailers = exchange.getRequest().getTrailers();
MetaData metaData = new MetaData(HttpVersion.HTTP_2, trailers.get());
Stream stream = getHttpChannel().getStream();
boolean lastContent = content.isLast();
HttpFields trailers = null;
boolean endStream = false;
if (lastContent)
{
trailers = trailerSupplier == null ? null : trailerSupplier.get();
endStream = trailers == null || trailers.size() == 0;
}
DataFrame dataFrame = new DataFrame(stream.getId(), content.getByteBuffer(), endStream);
HttpFields fTrailers = trailers;
stream.data(dataFrame, endStream || !lastContent ? callback : Callback.from(() -> sendTrailers(stream, fTrailers, callback), callback::failed));
}
private void sendTrailers(Stream stream, HttpFields trailers, Callback callback)
{
MetaData metaData = new MetaData(HttpVersion.HTTP_2, trailers);
HeadersFrame trailersFrame = new HeadersFrame(stream.getId(), metaData, null, true);
stream.headers(trailersFrame, callback);
}
private class HeadersPromise implements Promise<Stream>
{
private final HttpRequest request;
private final Callback callback;
private HeadersPromise(HttpRequest request, Callback callback)
{
this.request = request;
this.callback = callback;
}
@Override
public void succeeded(Stream stream)
{
HttpChannelOverHTTP2 channel = getHttpChannel();
channel.setStream(stream);
((IStream)stream).setAttachment(channel);
long idleTimeout = request.getIdleTimeout();
if (idleTimeout >= 0)
stream.setIdleTimeout(idleTimeout);
}
@Override
public void failed(Throwable x)
{
callback.failed(x);
}
}
}

View File

@ -0,0 +1,190 @@
//
// ========================================================================
// Copyright (c) 1995-2019 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.http2.client.http;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.client.HttpRequest;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.util.DeferredContentProvider;
import org.eclipse.jetty.client.util.StringContentProvider;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MetaData;
import org.eclipse.jetty.http2.api.Stream;
import org.eclipse.jetty.http2.api.server.ServerSessionListener;
import org.eclipse.jetty.http2.frames.DataFrame;
import org.eclipse.jetty.http2.frames.HeadersFrame;
import org.eclipse.jetty.util.Callback;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class RequestTrailersTest extends AbstractTest
{
@Test
public void testEmptyTrailersWithoutContent() throws Exception
{
testEmptyTrailers(null);
}
@Test
public void testEmptyTrailersWithEagerContent() throws Exception
{
testEmptyTrailers("eager_content");
}
private void testEmptyTrailers(String content) throws Exception
{
CountDownLatch trailersLatch = new CountDownLatch(1);
start(new ServerSessionListener.Adapter()
{
@Override
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
{
MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields());
HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true);
stream.headers(responseFrame, Callback.NOOP);
return new Stream.Listener.Adapter()
{
@Override
public void onHeaders(Stream stream, HeadersFrame frame)
{
trailersLatch.countDown();
}
};
}
});
HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort());
HttpFields trailers = new HttpFields();
request.trailers(() -> trailers);
if (content != null)
request.content(new StringContentProvider(content));
ContentResponse response = request.send();
assertEquals(HttpStatus.OK_200, response.getStatus());
// The client must not send the trailers.
assertFalse(trailersLatch.await(1, TimeUnit.SECONDS));
}
@Test
public void testEmptyTrailersWithDeferredContent() throws Exception
{
start(new ServerSessionListener.Adapter()
{
@Override
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
{
return new Stream.Listener.Adapter()
{
@Override
public void onData(Stream stream, DataFrame dataFrame, Callback callback)
{
callback.succeeded();
// We should not receive an empty HEADERS frame for the
// trailers, but instead a DATA frame with endStream=true.
if (dataFrame.isEndStream())
{
MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields());
HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true);
stream.headers(responseFrame, Callback.NOOP);
}
}
};
}
});
HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort());
HttpFields trailers = new HttpFields();
request.trailers(() -> trailers);
DeferredContentProvider content = new DeferredContentProvider();
request.content(content);
CountDownLatch latch = new CountDownLatch(1);
request.send(result ->
{
assertTrue(result.isSucceeded());
assertEquals(HttpStatus.OK_200, result.getResponse().getStatus());
latch.countDown();
});
// Send deferred content after a while.
Thread.sleep(1000);
content.offer(ByteBuffer.wrap("deferred_content".getBytes(StandardCharsets.UTF_8)));
content.close();
assertTrue(latch.await(5, TimeUnit.SECONDS));
}
@Test
public void testEmptyTrailersWithEmptyDeferredContent() throws Exception
{
start(new ServerSessionListener.Adapter()
{
@Override
public Stream.Listener onNewStream(Stream stream, HeadersFrame frame)
{
return new Stream.Listener.Adapter()
{
@Override
public void onData(Stream stream, DataFrame dataFrame, Callback callback)
{
callback.succeeded();
// We should not receive an empty HEADERS frame for the
// trailers, but instead a DATA frame with endStream=true.
if (dataFrame.isEndStream())
{
MetaData.Response response = new MetaData.Response(HttpVersion.HTTP_2, HttpStatus.OK_200, new HttpFields());
HeadersFrame responseFrame = new HeadersFrame(stream.getId(), response, null, true);
stream.headers(responseFrame, Callback.NOOP);
}
}
};
}
});
HttpRequest request = (HttpRequest)client.newRequest("localhost", connector.getLocalPort());
HttpFields trailers = new HttpFields();
request.trailers(() -> trailers);
DeferredContentProvider content = new DeferredContentProvider();
request.content(content);
CountDownLatch latch = new CountDownLatch(1);
request.send(result ->
{
assertTrue(result.isSucceeded());
assertEquals(HttpStatus.OK_200, result.getResponse().getStatus());
latch.countDown();
});
// Send deferred content after a while.
Thread.sleep(1000);
content.close();
assertTrue(latch.await(5, TimeUnit.SECONDS));
}
}

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty.http2</groupId>
<artifactId>http2-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>infinispan-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>infinispan-common</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>infinispan-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>infinispan-embedded-query</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>infinispan-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>infinispan-embedded</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>infinispan-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>infinispan-remote-query</artifactId>

View File

@ -1,5 +1,5 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd">
<Configure id="Server" class="org.eclipse.jetty.server.Server">
<!-- ============================================================= -->

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>infinispan-parent</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>infinispan-remote</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>

View File

@ -2,7 +2,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>9.4.19-SNAPSHOT</version>
<version>9.4.20-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-io</artifactId>

View File

@ -307,9 +307,36 @@ abstract public class WriteFlusher
private void fail(Callback callback, Throwable... suppressed)
{
FailedState failed = (FailedState)_state.get();
Throwable cause;
loop:
while (true)
{
State state = _state.get();
switch (state.getType())
{
case FAILED:
{
FailedState failed = (FailedState)state;
cause = failed.getCause();
break loop;
}
case IDLE:
for (Throwable t : suppressed)
LOG.warn(t);
return;
default:
Throwable t = new IllegalStateException();
if (!_state.compareAndSet(state, new FailedState(t)))
continue;
cause = t;
break loop;
}
}
Throwable cause = failed.getCause();
for (Throwable t : suppressed)
{
if (t != cause)

View File

@ -25,7 +25,6 @@ import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
@ -41,6 +40,7 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.WriteFlusher;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.Invocable;
@ -584,7 +584,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
if (LOG.isDebugEnabled())
LOG.debug("unwrap net_filled={} {} encryptedBuffer={} unwrapBuffer={} appBuffer={}",
net_filled,
unwrapResult.toString().replace('\n', ' '),
StringUtil.replace(unwrapResult.toString(), '\n', ' '),
BufferUtil.toSummaryString(_encryptedInput),
BufferUtil.toDetailString(app_in),
BufferUtil.toDetailString(buffer));
@ -895,7 +895,7 @@ public class SslConnection extends AbstractConnection implements Connection.Upgr
}
if (LOG.isDebugEnabled())
LOG.debug("wrap {} {} ioDone={}/{}",
wrapResult.toString().replace('\n', ' '),
StringUtil.replace(wrapResult.toString(), '\n', ' '),
BufferUtil.toSummaryString(_encryptedOutput),
_sslEngine.isInboundDone(),
_sslEngine.isOutboundDone());

View File

@ -18,14 +18,6 @@
package org.eclipse.jetty.io;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.nio.ByteBuffer;
@ -43,10 +35,18 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.log.StacklessLogging;
import org.hamcrest.Matchers;
import org.junit.jupiter.api.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.instanceOf;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
public class WriteFlusherTest
{
@Test
@ -159,6 +159,43 @@ public class WriteFlusherTest
assertTrue(flusher.isIdle());
}
@Test
public void testCallbackThrows() throws Exception
{
ByteArrayEndPoint endPoint = new ByteArrayEndPoint(new byte[0], 100);
AtomicBoolean incompleteFlush = new AtomicBoolean(false);
WriteFlusher flusher = new WriteFlusher(endPoint)
{
@Override
protected void onIncompleteFlush()
{
incompleteFlush.set(true);
}
};
FutureCallback callback = new FutureCallback()
{
@Override
public void succeeded()
{
super.succeeded();
throw new IllegalStateException();
}
};
try (StacklessLogging stacklessLogging = new StacklessLogging(WriteFlusher.class))
{
flusher.write(callback, BufferUtil.toBuffer("How now brown cow!"));
callback.get(100, TimeUnit.MILLISECONDS);
}
assertEquals("How now brown cow!", endPoint.takeOutputString());
assertTrue(callback.isDone());
assertFalse(incompleteFlush.get());
assertTrue(flusher.isIdle());
}
@Test
public void testCloseWhileBlocking() throws Exception
{

Some files were not shown because too many files have changed in this diff Show More