Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'jetty-server')
-rw-r--r--jetty-server/pom.xml2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java38
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java9
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java20
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java18
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java7
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/InclusiveByteRange.java4
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java5
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Request.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Response.java16
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java14
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Server.java34
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java34
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java47
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java102
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java274
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java101
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java9
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java9
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java1
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java42
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java19
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java4
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java10
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java4
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java31
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java1
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java10
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java1
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java1
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java9
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java197
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ShutdownMonitorTest.java76
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java201
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java26
-rw-r--r--jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java10
50 files changed, 986 insertions, 436 deletions
diff --git a/jetty-server/pom.xml b/jetty-server/pom.xml
index 3a3f5ee4fb..d2a4d712db 100644
--- a/jetty-server/pom.xml
+++ b/jetty-server/pom.xml
@@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
- <version>9.2.2-SNAPSHOT</version>
+ <version>9.2.3-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
index 7d3402fbfa..3106eec257 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
@@ -19,8 +19,6 @@
package org.eclipse.jetty.server;
import java.io.IOException;
-import java.net.Socket;
-import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -37,9 +35,7 @@ import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.io.ArrayByteBufferPool;
import org.eclipse.jetty.io.ByteBufferPool;
-import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
-import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.util.FutureCallback;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
@@ -47,7 +43,6 @@ import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
@@ -145,7 +140,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
private final Scheduler _scheduler;
private final ByteBufferPool _byteBufferPool;
private final Thread[] _acceptors;
- private final Set<EndPoint> _endpoints = Collections.newSetFromMap(new ConcurrentHashMap());
+ private final Set<EndPoint> _endpoints = Collections.newSetFromMap(new ConcurrentHashMap<EndPoint, Boolean>());
private final Set<EndPoint> _immutableEndPoints = Collections.unmodifiableSet(_endpoints);
private volatile CountDownLatch _stopping;
private long _idleTimeout = 30000;
@@ -191,9 +186,9 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
int cores = Runtime.getRuntime().availableProcessors();
if (acceptors < 0)
- acceptors = 1 + cores / 16;
- if (acceptors > 2 * cores)
- LOG.warn("Acceptors should be <= 2*availableProcessors: " + this);
+ acceptors=Math.max(1, Math.min(4,cores/8));
+ if (acceptors > cores)
+ LOG.warn("Acceptors should be <= availableProcessors: " + this);
_acceptors = new Thread[acceptors];
}
@@ -261,7 +256,11 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
_stopping=new CountDownLatch(_acceptors.length);
for (int i = 0; i < _acceptors.length; i++)
- getExecutor().execute(new Acceptor(i));
+ {
+ Acceptor a = new Acceptor(i);
+ addBean(a);
+ getExecutor().execute(a);
+ }
LOG.info("Started {}", this);
}
@@ -299,6 +298,9 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
_stopping=null;
super.doStop();
+
+ for (Acceptor a : getBeans(Acceptor.class))
+ removeBean(a);
LOG.info("Stopped {}", this);
}
@@ -440,6 +442,7 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
private class Acceptor implements Runnable
{
private final int _acceptor;
+ private String _name;
private Acceptor(int id)
{
@@ -450,8 +453,9 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
public void run()
{
Thread current = Thread.currentThread();
- String name = current.getName();
- current.setName(name + "-acceptor-" + _acceptor + "-" + AbstractConnector.this);
+ String name=current.getName();
+ _name=String.format("%s-acceptor-%d@%x-%s",name,_acceptor,hashCode(),AbstractConnector.this.toString());
+ current.setName(_name);
synchronized (AbstractConnector.this)
{
@@ -488,6 +492,16 @@ public abstract class AbstractConnector extends ContainerLifeCycle implements Co
stopping.countDown();
}
}
+
+ @Override
+ public String toString()
+ {
+ String name=_name;
+ if (name==null)
+ return String.format("acceptor-%d@%x", _acceptor, hashCode());
+ return name;
+ }
+
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java
index dcaecbe50f..2a16bdd550 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractNCSARequestLog.java
@@ -25,7 +25,6 @@ import javax.servlet.http.Cookie;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.PathMap;
-import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java
index ce4544c900..0ea12cc734 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java
@@ -24,7 +24,6 @@ import java.util.concurrent.Executor;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint;
-import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.Graceful;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
index 891e8ee1cf..ff8f14763d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ForwardedRequestCustomizer.java
@@ -20,8 +20,6 @@ package org.eclipse.jetty.server;
import java.net.InetSocketAddress;
-import javax.servlet.ServletRequest;
-
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java
index cfe7b9a200..6b7f11fb1b 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Handler.java
@@ -24,8 +24,6 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
-import org.eclipse.jetty.server.handler.HandlerCollection;
-import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.ManagedOperation;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java
index b39b25dcf4..7911351ef0 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HostHeaderCustomizer.java
@@ -20,8 +20,6 @@ package org.eclipse.jetty.server;
import java.util.Objects;
-import javax.servlet.http.HttpServletRequest;
-
/**
* Customizes requests that lack the {@code Host} header (for example, HTTP 1.0 requests).
* <p />
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
index e86001ed54..9248d9f874 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannel.java
@@ -397,10 +397,14 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
_state.completed();
if (!_response.isCommitted() && !_request.isHandled())
+ {
_response.sendError(404);
+ }
else
+ {
// Complete generating the response
_response.closeOutput();
+ }
}
catch(EofException|ClosedChannelException e)
{
@@ -795,10 +799,11 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable, H
/**
* If a write or similar to this channel fails this method should be called. The standard implementation
- * of {@link #failed()} is a noop. But the different implementations of HttpChannel might want to take actions.
+ * is to call {@link HttpTransport#abort()}
*/
- public void failed()
+ public void abort()
{
+ _transport.abort();
}
private class CommitCallback implements Callback
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
index 352af25c75..f9c5054714 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConfiguration.java
@@ -54,6 +54,23 @@ public class HttpConfiguration
private boolean _sendXPoweredBy = false; //send X-Powered-By: header
private boolean _sendDateHeader = true; //send Date: header
+
+ /* ------------------------------------------------------------ */
+ /**
+ * <p>An interface that allows a request object to be customized
+ * for a particular HTTP connector configuration. Unlike Filters, customizer are
+ * applied before the request is submitted for processing and can be specific to the
+ * connector on which the request was received.
+ *
+ * <p>Typically Customizers perform tasks such as: <ul>
+ * <li>process header fields that may be injected by a proxy or load balancer.
+ * <li>setup attributes that may come from the connection/connector such as SSL Session IDs
+ * <li>Allow a request to be marked as secure or authenticated if those have been offloaded
+ * and communicated by header, cookie or other out-of-band mechanism
+ * <li>Set request attributes/fields that are determined by the connector on which the
+ * request was received
+ * </ul>
+ */
public interface Customizer
{
public void customize(Connector connector, HttpConfiguration channelConfig, Request request);
@@ -103,7 +120,8 @@ public class HttpConfiguration
{
return _customizers;
}
-
+
+ /* ------------------------------------------------------------ */
public <T> T getCustomizer(Class<T> type)
{
for (Customizer c : _customizers)
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
index 4d41cce3ab..cec4058cf6 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java
@@ -426,11 +426,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
@Override
public void onClose()
{
- if (_sendCallback.isInUse())
- {
- LOG.warn("Closed with pending write:"+this);
- _sendCallback.failed(new EofException("Connection closed"));
- }
+ _sendCallback.close();
super.onClose();
}
@@ -541,11 +537,11 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
}
@Override
- public void failed()
+ public void abort()
{
- getEndPoint().shutdownOutput();
+ super.abort();
+ _generator.setPersistent(false);
}
-
@Override
public boolean messageComplete()
@@ -580,6 +576,10 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
_header = null;
_shutdownOut = false;
}
+ else if (isClosed())
+ {
+ callback.failed(new EofException());
+ }
else
{
callback.failed(new WritePendingException());
@@ -705,7 +705,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
@Override
public String toString()
{
- return String.format("SendCB@%x{s=%s,i=%s,cb=%s}",hashCode(),getState(),_info,_callback);
+ return String.format("%s[i=%s,cb=%s]",super.toString(),_info,_callback);
}
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
index d638984a39..12a23d5fb3 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java
@@ -24,10 +24,7 @@ import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritePendingException;
import java.util.concurrent.atomic.AtomicReference;
-import javax.servlet.RequestDispatcher;
import javax.servlet.ServletOutputStream;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
import javax.servlet.WriteListener;
import org.eclipse.jetty.http.HttpContent;
@@ -160,7 +157,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
catch(IOException e)
{
LOG.debug(e);
- _channel.failed();
+ _channel.abort();
}
releaseBuffer();
return;
@@ -195,7 +192,7 @@ public class HttpOutput extends ServletOutputStream implements Runnable
catch(IOException e)
{
LOG.debug(e);
- _channel.failed();
+ _channel.abort();
}
releaseBuffer();
return;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/InclusiveByteRange.java b/jetty-server/src/main/java/org/eclipse/jetty/server/InclusiveByteRange.java
index cb81d3c95e..95e894afc2 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/InclusiveByteRange.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/InclusiveByteRange.java
@@ -81,7 +81,7 @@ public class InclusiveByteRange
* @param size Size of the resource.
* @return LazyList of satisfiable ranges
*/
- public static List<InclusiveByteRange> satisfiableRanges(Enumeration headers, long size)
+ public static List<InclusiveByteRange> satisfiableRanges(Enumeration<String> headers, long size)
{
Object satRanges=null;
@@ -89,7 +89,7 @@ public class InclusiveByteRange
headers:
while (headers.hasMoreElements())
{
- String header = (String) headers.nextElement();
+ String header = headers.nextElement();
StringTokenizer tok = new StringTokenizer(header,"=,",false);
String t=null;
try
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java
index 1f05003a3d..26ff80fb5b 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java
@@ -138,7 +138,8 @@ public class LocalConnector extends AbstractConnector
LocalEndPoint endp = executeRequest(requestsBuffer);
endp.waitUntilClosedOrIdleFor(idleFor,units);
ByteBuffer responses = endp.takeOutput();
- endp.getConnection().close();
+ if (endp.isOutputShutdown())
+ endp.close();
if (LOG.isDebugEnabled())
LOG.debug("responses {}", BufferUtil.toUTF8String(responses));
return responses;
@@ -157,6 +158,8 @@ public class LocalConnector extends AbstractConnector
private LocalEndPoint executeRequest(ByteBuffer rawRequest)
{
+ if (!isStarted())
+ throw new IllegalStateException("!STARTED");
LocalEndPoint endp = new LocalEndPoint();
endp.setInput(rawRequest);
_connects.add(endp);
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
index 8dbb07792f..330bb40cd9 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Request.java
@@ -1247,7 +1247,7 @@ public class Request implements HttpServletRequest
_port=0;
return _serverName;
}
- _serverName = hostPort.substring(1,len-1);
+ _serverName = hostPort.substring(0,len);
}
else if (len==hostPort.length())
_serverName=hostPort;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java
index e39c4a60fb..dc686260cd 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ResourceCache.java
@@ -33,7 +33,6 @@ import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.http.DateGenerator;
import org.eclipse.jetty.http.HttpContent;
-import org.eclipse.jetty.http.HttpContent.ResourceAsHttpContent;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.log.Log;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java
index eb95e20401..79f4e4989c 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Response.java
@@ -541,10 +541,7 @@ public class Response implements HttpServletResponse
@Override
public void sendError(int sc) throws IOException
{
- if (sc == 102)
- sendProcessing();
- else
- sendError(sc, null);
+ sendError(sc, null);
}
@Override
@@ -553,6 +550,17 @@ public class Response implements HttpServletResponse
if (isIncluding())
return;
+ switch(code)
+ {
+ case -1:
+ _channel.abort();
+ return;
+ case 102:
+ sendProcessing();
+ return;
+ default:
+ }
+
if (isCommitted())
LOG.warn("Committed before "+code+" "+message);
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java
index b017461310..dd26b04b14 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SecureRequestCustomizer.java
@@ -20,8 +20,10 @@ package org.eclipse.jetty.server;
import java.security.cert.X509Certificate;
+import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
+import javax.servlet.ServletRequest;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.io.ssl.SslConnection;
@@ -31,6 +33,12 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
+
+/* ------------------------------------------------------------ */
+/** Customizer that extracts the attribute from an {@link SSLContext}
+ * and sets them on the request with {@link ServletRequest#setAttribute(String, Object)}
+ * according to Servlet Specification Requirements.
+ */
public class SecureRequestCustomizer implements HttpConfiguration.Customizer
{
private static final Logger LOG = Log.getLogger(SecureRequestCustomizer.class);
@@ -40,7 +48,6 @@ public class SecureRequestCustomizer implements HttpConfiguration.Customizer
*/
public static final String CACHED_INFO_ATTR = CachedInfo.class.getName();
-
@Override
public void customize(Connector connector, HttpConfiguration channelConfig, Request request)
{
@@ -53,14 +60,11 @@ public class SecureRequestCustomizer implements HttpConfiguration.Customizer
SSLEngine sslEngine=sslConnection.getSSLEngine();
customize(sslEngine,request);
}
-
}
/* ------------------------------------------------------------ */
/*
- * Allow the Listener a chance to customise the request. before the server
- * does its stuff. <br>
- * This allows the required attributes to be set for SSL requests. <br>
+ * Customise the request attributes to be set for SSL requests. <br>
* The requirements of the Servlet specs are:
* <ul>
* <li> an attribute named "javax.servlet.request.ssl_session_id" of type
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
index 66919f42a7..ce4bdd9097 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java
@@ -18,6 +18,7 @@
package org.eclipse.jetty.server;
+import java.awt.geom.PathIterator;
import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.net.InetAddress;
@@ -32,6 +33,7 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
+
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -46,11 +48,13 @@ import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
+import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.Jetty;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.URIUtil;
+import org.eclipse.jetty.util.UrlEncoded;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.Name;
@@ -143,6 +147,25 @@ public class Server extends HandlerWrapper implements Attributes
}
/* ------------------------------------------------------------ */
+ /**
+ * Set a graceful stop time.
+ * The {@link StatisticsHandler} must be configured so that open connections can
+ * be tracked for a graceful shutdown.
+ * @see org.eclipse.jetty.util.component.ContainerLifeCycle#setStopTimeout(long)
+ */
+ @Override
+ public void setStopTimeout(long stopTimeout)
+ {
+ super.setStopTimeout(stopTimeout);
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Set stop server at shutdown behaviour.
+ * @param stop If true, this server instance will be explicitly stopped when the
+ * JVM is shutdown. Otherwise the JVM is stopped with the server running.
+ * @see Runtime#addShutdownHook(Thread)
+ * @see ShutdownThread
+ */
public void setStopAtShutdown(boolean stop)
{
//if we now want to stop
@@ -397,7 +420,7 @@ public class Server extends HandlerWrapper implements Attributes
}
catch (Exception e)
{
- mex.add(e.getCause());
+ mex.add(e);
}
}
}
@@ -474,7 +497,6 @@ public class Server extends HandlerWrapper implements Attributes
response.sendError(HttpStatus.BAD_REQUEST_400);
request.setHandled(true);
response.setStatus(200);
- response.getHttpFields().put(HttpHeader.ALLOW,"GET,POST,HEAD,OPTIONS");
response.setContentLength(0);
response.closeOutput();
}
@@ -492,15 +514,15 @@ public class Server extends HandlerWrapper implements Attributes
final Request baseRequest=connection.getRequest();
final String path=event.getPath();
-
+
if (path!=null)
{
// this is a dispatch with a path
ServletContext context=event.getServletContext();
- HttpURI uri = new HttpURI(context==null?path:URIUtil.addPaths(context.getContextPath(),path));
+ HttpURI uri = new HttpURI(URIUtil.addPaths(context==null?null:context.getContextPath(), path));
baseRequest.setUri(uri);
baseRequest.setRequestURI(null);
- baseRequest.setPathInfo(baseRequest.getRequestURI());
+ baseRequest.setPathInfo(uri.getDecodedPath());
if (uri.getQuery()!=null)
baseRequest.mergeQueryParameters(uri.getQuery(), true); //we have to assume dispatch path and query are UTF8
}
@@ -606,6 +628,7 @@ public class Server extends HandlerWrapper implements Attributes
/**
* @return The URI of the first {@link NetworkConnector} and first {@link ContextHandler}, or null
*/
+ @SuppressWarnings("resource")
public URI getURI()
{
NetworkConnector connector=null;
@@ -652,6 +675,7 @@ public class Server extends HandlerWrapper implements Attributes
return this.getClass().getName()+"@"+Integer.toHexString(hashCode());
}
+ /* ------------------------------------------------------------ */
@Override
public void dump(Appendable out,String indent) throws IOException
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java
index a7d5fe0f2d..f4da30c004 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServerConnector.java
@@ -20,12 +20,10 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.InetSocketAddress;
-import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
-import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.Executor;
@@ -37,7 +35,6 @@ import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.SelectChannelEndPoint;
import org.eclipse.jetty.io.SelectorManager;
import org.eclipse.jetty.io.SelectorManager.ManagedSelector;
-import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.annotation.Name;
@@ -208,7 +205,8 @@ public class ServerConnector extends AbstractNetworkConnector
@Name("factories") ConnectionFactory... factories)
{
super(server,executor,scheduler,bufferPool,acceptors,factories);
- _manager = new ServerConnectorManager(getExecutor(), getScheduler(), selectors > 0 ? selectors : Runtime.getRuntime().availableProcessors());
+ _manager = new ServerConnectorManager(getExecutor(), getScheduler(),
+ selectors>0?selectors:Math.max(1,Math.min(4,Runtime.getRuntime().availableProcessors()/2)));
addBean(_manager, true);
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java
index 11f249e139..8ac5a48207 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ServletRequestHttpWrapper.java
@@ -48,126 +48,151 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
super(request);
}
+ @Override
public String getAuthType()
{
return null;
}
+ @Override
public Cookie[] getCookies()
{
return null;
}
+ @Override
public long getDateHeader(String name)
{
return 0;
}
+ @Override
public String getHeader(String name)
{
return null;
}
- public Enumeration getHeaders(String name)
+ @Override
+ public Enumeration<String> getHeaders(String name)
{
return null;
}
- public Enumeration getHeaderNames()
+ @Override
+ public Enumeration<String> getHeaderNames()
{
return null;
}
+ @Override
public int getIntHeader(String name)
{
return 0;
}
+ @Override
public String getMethod()
{
return null;
}
+ @Override
public String getPathInfo()
{
return null;
}
+ @Override
public String getPathTranslated()
{
return null;
}
+ @Override
public String getContextPath()
{
return null;
}
+ @Override
public String getQueryString()
{
return null;
}
+ @Override
public String getRemoteUser()
{
return null;
}
+ @Override
public boolean isUserInRole(String role)
{
return false;
}
+ @Override
public Principal getUserPrincipal()
{
return null;
}
+ @Override
public String getRequestedSessionId()
{
return null;
}
+ @Override
public String getRequestURI()
{
return null;
}
+ @Override
public StringBuffer getRequestURL()
{
return null;
}
+ @Override
public String getServletPath()
{
return null;
}
+ @Override
public HttpSession getSession(boolean create)
{
return null;
}
+ @Override
public HttpSession getSession()
{
return null;
}
+ @Override
public boolean isRequestedSessionIdValid()
{
return false;
}
+ @Override
public boolean isRequestedSessionIdFromCookie()
{
return false;
}
+ @Override
public boolean isRequestedSessionIdFromURL()
{
return false;
}
+ @Override
public boolean isRequestedSessionIdFromUrl()
{
return false;
@@ -176,6 +201,7 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
/**
* @see javax.servlet.http.HttpServletRequest#authenticate(javax.servlet.http.HttpServletResponse)
*/
+ @Override
public boolean authenticate(HttpServletResponse response) throws IOException, ServletException
{
return false;
@@ -184,6 +210,7 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
/**
* @see javax.servlet.http.HttpServletRequest#getPart(java.lang.String)
*/
+ @Override
public Part getPart(String name) throws IOException, ServletException
{
return null;
@@ -192,6 +219,7 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
/**
* @see javax.servlet.http.HttpServletRequest#getParts()
*/
+ @Override
public Collection<Part> getParts() throws IOException, ServletException
{
return null;
@@ -200,6 +228,7 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
/**
* @see javax.servlet.http.HttpServletRequest#login(java.lang.String, java.lang.String)
*/
+ @Override
public void login(String username, String password) throws ServletException
{
@@ -208,6 +237,7 @@ public class ServletRequestHttpWrapper extends ServletRequestWrapper implements
/**
* @see javax.servlet.http.HttpServletRequest#logout()
*/
+ @Override
public void logout() throws ServletException
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java
index 267391b56d..d6ca22d61e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java
@@ -23,7 +23,6 @@ import java.util.Set;
import javax.servlet.SessionCookieConfig;
import javax.servlet.SessionTrackingMode;
-import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java
index abc6d61ef8..38b866574d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java
@@ -54,20 +54,18 @@ public class ShutdownMonitor
}
/**
- * ShutdownMonitorThread
+ * ShutdownMonitorRunnable
*
* Thread for listening to STOP.PORT for command to stop Jetty.
* If ShowndownMonitor.exitVm is true, then Sytem.exit will also be
* called after the stop.
*
*/
- public class ShutdownMonitorThread extends Thread
+ private class ShutdownMonitorRunnable implements Runnable
{
-
- public ShutdownMonitorThread ()
+ public ShutdownMonitorRunnable()
{
- setDaemon(true);
- setName("ShutdownMonitor");
+ startListenSocket();
}
@Override
@@ -102,7 +100,7 @@ public class ShutdownMonitor
// Graceful Shutdown
debug("Issuing graceful shutdown..");
ShutdownThread.getInstance().run();
-
+
//Stop accepting any more
close(serverSocket);
serverSocket = null;
@@ -148,28 +146,7 @@ public class ShutdownMonitor
}
}
- public void start()
- {
- if (isAlive())
- {
- // TODO why are we reentrant here?
- if (DEBUG)
- System.err.printf("ShutdownMonitorThread already started");
- return; // cannot start it again
- }
-
- startListenSocket();
-
- if (serverSocket == null)
- {
- return;
- }
- if (DEBUG)
- System.err.println("Starting ShutdownMonitorThread");
- super.start();
- }
-
- private void startListenSocket()
+ public void startListenSocket()
{
if (port < 0)
{
@@ -217,9 +194,7 @@ public class ShutdownMonitor
private String key;
private boolean exitVm;
private ServerSocket serverSocket;
- private ShutdownMonitorThread thread;
-
-
+ private Thread thread;
/**
* Create a ShutdownMonitor using configuration from the System properties.
@@ -372,18 +347,20 @@ public class ShutdownMonitor
protected void start() throws Exception
{
- ShutdownMonitorThread t = null;
+ Thread t = null;
+
synchronized (this)
{
if (thread != null && thread.isAlive())
{
- // TODO why are we reentrant here?
if (DEBUG)
System.err.printf("ShutdownMonitorThread already started");
return; // cannot start it again
}
- thread = new ShutdownMonitorThread();
+ thread = new Thread(new ShutdownMonitorRunnable());
+ thread.setDaemon(true);
+ thread.setName("ShutdownMonitor");
t = thread;
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java
index 0d54e536fb..16a09aca5f 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/AbstractHandlerContainer.java
@@ -58,6 +58,7 @@ public abstract class AbstractHandlerContainer extends AbstractHandler implement
}
/* ------------------------------------------------------------ */
+ @SuppressWarnings("unchecked")
@Override
public <T extends Handler> T getChildHandlerByClass(Class<T> byclass)
{
@@ -103,6 +104,7 @@ public abstract class AbstractHandlerContainer extends AbstractHandler implement
{
for (Handler h:branches)
{
+ @SuppressWarnings("unchecked")
T container = (T)h;
Handler[] candidates = container.getChildHandlersByClass(handler.getClass());
if (candidates!=null)
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
index f01f73a4ab..ed6efd1b65 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
@@ -36,7 +36,6 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
-import java.util.ListIterator;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
@@ -67,7 +66,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.server.ClassLoaderDump;
-import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HandlerContainer;
@@ -108,7 +106,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
{
public final static int SERVLET_MAJOR_VERSION=3;
public final static int SERVLET_MINOR_VERSION=0;
- public static final Class[] SERVLET_LISTENER_TYPES = new Class[] {ServletContextListener.class,
+ public static final Class<?>[] SERVLET_LISTENER_TYPES = new Class[] {ServletContextListener.class,
ServletContextAttributeListener.class,
ServletRequestListener.class,
ServletRequestAttributeListener.class};
@@ -510,8 +508,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
/*
* @see javax.servlet.ServletContext#getInitParameterNames()
*/
- @SuppressWarnings("rawtypes")
- public Enumeration getInitParameterNames()
+ public Enumeration<String> getInitParameterNames()
{
return Collections.enumeration(_initParams.keySet());
}
@@ -873,27 +870,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
_scontext.clearAttributes();
}
- /* ------------------------------------------------------------ */
- /*
- * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
- */
- public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException
+ public boolean checkVirtualHost(final Request baseRequest)
{
- DispatcherType dispatch = baseRequest.getDispatcherType();
-
- switch (_availability)
- {
- case SHUTDOWN:
- case UNAVAILABLE:
- baseRequest.setHandled(true);
- response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
- return false;
- default:
- if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
- return false;
- }
-
- // Check the vhosts
if (_vhosts != null && _vhosts.length > 0)
{
String vhost = normalizeHostname(baseRequest.getServerName());
@@ -929,27 +907,61 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (!match || connectorName && !connectorMatch)
return false;
}
-
+ return true;
+ }
+
+ public boolean checkContextPath(String uri)
+ {
// Are we not the root context?
if (_contextPath.length() > 1)
{
// reject requests that are not for us
- if (!target.startsWith(_contextPath))
+ if (!uri.startsWith(_contextPath))
return false;
- if (target.length() > _contextPath.length() && target.charAt(_contextPath.length()) != '/')
+ if (uri.length() > _contextPath.length() && uri.charAt(_contextPath.length()) != '/')
return false;
+ }
+ return true;
+ }
+
+ /* ------------------------------------------------------------ */
+ /*
+ * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ */
+ public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException
+ {
+ DispatcherType dispatch = baseRequest.getDispatcherType();
- // redirect null path infos
- if (!_allowNullPathInfo && _contextPath.length() == target.length())
- {
- // context request must end with /
+ // Check the vhosts
+ if (!checkVirtualHost(baseRequest))
+ return false;
+
+ if (!checkContextPath(target))
+ return false;
+
+ // Are we not the root context?
+ // redirect null path infos
+ if (!_allowNullPathInfo && _contextPath.length() == target.length() && _contextPath.length()>1)
+ {
+ // context request must end with /
+ baseRequest.setHandled(true);
+ if (baseRequest.getQueryString() != null)
+ response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString());
+ else
+ response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
+ return false;
+ }
+
+ switch (_availability)
+ {
+ case SHUTDOWN:
+ case UNAVAILABLE:
baseRequest.setHandled(true);
- if (baseRequest.getQueryString() != null)
- response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString());
- else
- response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
+ response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return false;
- }
+ default:
+ if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
+ return false;
}
return true;
@@ -1129,7 +1141,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (!_requestAttributeListeners.isEmpty())
{
- ListIterator<ServletRequestAttributeListener> iter = _requestAttributeListeners.listIterator(_requestAttributeListeners.size());
for (int i=_requestAttributeListeners.size();i-->0;)
baseRequest.removeEventListener(_requestAttributeListeners.get(i));
}
@@ -1648,10 +1659,15 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
}
/* ------------------------------------------------------------ */
+ /**
+ * @param path
+ * @param resource
+ * @return True if the alias is OK
+ */
public boolean checkAlias(String path, Resource resource)
{
// Is the resource aliased?
- if (resource.getAlias() != null)
+ if (resource.getAlias() != null)
{
if (LOG.isDebugEnabled())
LOG.debug("Aliased resource: " + resource + "~=" + resource.getAlias());
@@ -1880,7 +1896,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
matched_path = context_path;
}
- if (matched_path.equals(context_path))
+ if (matched_path != null && matched_path.equals(context_path))
contexts.add(ch);
}
}
@@ -2058,7 +2074,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
/*
* @see javax.servlet.ServletContext#getInitParameterNames()
*/
- @SuppressWarnings("unchecked")
@Override
public Enumeration<String> getInitParameterNames()
{
@@ -2195,6 +2210,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
try
{
+ @SuppressWarnings("unchecked")
Class<? extends EventListener> clazz = _classLoader==null?Loader.loadClass(ContextHandler.class,className):_classLoader.loadClass(className);
addListener(clazz);
}
@@ -2289,9 +2305,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
//classloader, or a parent of it
try
{
- Class reflect = Loader.loadClass(getClass(), "sun.reflect.Reflection");
+ Class<?> reflect = Loader.loadClass(getClass(), "sun.reflect.Reflection");
Method getCallerClass = reflect.getMethod("getCallerClass", Integer.TYPE);
- Class caller = (Class)getCallerClass.invoke(null, 2);
+ Class<?> caller = (Class<?>)getCallerClass.invoke(null, 2);
boolean ok = false;
ClassLoader callerLoader = caller.getClassLoader();
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java
index 4ade364903..2d77d1c2af 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java
@@ -19,6 +19,15 @@
package org.eclipse.jetty.server.handler;
import java.io.IOException;
+import java.lang.reflect.Array;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -52,7 +61,8 @@ public class ContextHandlerCollection extends HandlerCollection
{
private static final Logger LOG = Log.getLogger(ContextHandlerCollection.class);
- private volatile Trie<ContextHandler[]> _contexts;
+ private final ConcurrentMap<ContextHandler,Handler> _contextBranches = new ConcurrentHashMap<>();
+ private volatile Trie<Map.Entry<String,Branch[]>> _pathBranches;
private Class<? extends ContextHandler> _contextClass = ContextHandler.class;
/* ------------------------------------------------------------ */
@@ -69,71 +79,70 @@ public class ContextHandlerCollection extends HandlerCollection
@ManagedOperation("update the mapping of context path to context")
public void mapContexts()
{
- int capacity=512;
+ _contextBranches.clear();
+
+ if (getHandlers()==null)
+ {
+ _pathBranches=new ArrayTernaryTrie<>(false,16);
+ return;
+ }
+
+ // Create map of contextPath to handler Branch
+ Map<String,Branch[]> map = new HashMap<>();
+ for (Handler handler:getHandlers())
+ {
+ Branch branch=new Branch(handler);
+ for (String contextPath : branch.getContextPaths())
+ {
+ Branch[] branches=map.get(contextPath);
+ map.put(contextPath, ArrayUtil.addToArray(branches, branch, Branch.class));
+ }
+
+ for (ContextHandler context : branch.getContextHandlers())
+ _contextBranches.putIfAbsent(context, branch.getHandler());
+ }
+
+ // Sort the branches so those with virtual hosts are considered before those without
+ for (Map.Entry<String,Branch[]> entry: map.entrySet())
+ {
+ Branch[] branches=entry.getValue();
+ Branch[] sorted=new Branch[branches.length];
+ int i=0;
+ for (Branch branch:branches)
+ if (branch.hasVirtualHost())
+ sorted[i++]=branch;
+ for (Branch branch:branches)
+ if (!branch.hasVirtualHost())
+ sorted[i++]=branch;
+ entry.setValue(sorted);
+ }
// Loop until we have a big enough trie to hold all the context paths
- Trie<ContextHandler[]> trie;
+ int capacity=512;
+ Trie<Map.Entry<String,Branch[]>> trie;
loop: while(true)
{
trie=new ArrayTernaryTrie<>(false,capacity);
-
- Handler[] branches = getHandlers();
-
- // loop over each group of contexts
- for (int b=0;branches!=null && b<branches.length;b++)
+ for (Map.Entry<String,Branch[]> entry: map.entrySet())
{
- Handler[] handlers=null;
-
- if (branches[b] instanceof ContextHandler)
+ if (!trie.put(entry.getKey().substring(1),entry))
{
- handlers = new Handler[]{ branches[b] };
- }
- else if (branches[b] instanceof HandlerContainer)
- {
- handlers = ((HandlerContainer)branches[b]).getChildHandlersByClass(ContextHandler.class);
- }
- else
- continue;
-
- // for each context handler in a group
- for (int i=0;handlers!=null && i<handlers.length;i++)
- {
- ContextHandler handler=(ContextHandler)handlers[i];
- String contextPath=handler.getContextPath().substring(1);
- ContextHandler[] contexts=trie.get(contextPath);
-
- if (!trie.put(contextPath,ArrayUtil.addToArray(contexts,handler,ContextHandler.class)))
- {
- capacity+=512;
- continue loop;
- }
+ capacity+=512;
+ continue loop;
}
}
-
- break;
+ break loop;
}
+
- // Sort the contexts so those with virtual hosts are considered before those without
- for (String ctx : trie.keySet())
+ if (LOG.isDebugEnabled())
{
- ContextHandler[] contexts=trie.get(ctx);
- ContextHandler[] sorted=new ContextHandler[contexts.length];
- int i=0;
- for (ContextHandler handler:contexts)
- if (handler.getVirtualHosts()!=null && handler.getVirtualHosts().length>0)
- sorted[i++]=handler;
- for (ContextHandler handler:contexts)
- if (handler.getVirtualHosts()==null || handler.getVirtualHosts().length==0)
- sorted[i++]=handler;
- trie.put(ctx,sorted);
+ for (String ctx : trie.keySet())
+ LOG.debug("{}->{}",ctx,Arrays.asList(trie.get(ctx).getValue()));
}
-
- //for (String ctx : trie.keySet())
- // System.err.printf("'%s'->%s%n",ctx,Arrays.asList(trie.get(ctx)));
- _contexts=trie;
+ _pathBranches=trie;
}
-
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.server.handler.HandlerCollection#setHandlers(org.eclipse.jetty.server.server.Handler[])
@@ -164,60 +173,66 @@ public class ContextHandlerCollection extends HandlerCollection
{
Handler[] handlers = getHandlers();
if (handlers==null || handlers.length==0)
- return;
+ return;
- HttpChannelState async = baseRequest.getHttpChannelState();
- if (async.isAsync())
- {
- ContextHandler context=async.getContextHandler();
- if (context!=null)
- {
- context.handle(target,baseRequest,request, response);
- return;
- }
- }
-
- // data structure which maps a request to a context; first-best match wins
- // { context path => [ context ] }
- // }
- if (target.startsWith("/"))
- {
- int limit = target.length()-1;
-
- while (limit>=0)
- {
- // Get best match
- ContextHandler[] contexts = _contexts.getBest(target,1,limit);
- if (contexts==null)
- break;
+ HttpChannelState async = baseRequest.getHttpChannelState();
+ if (async.isAsync())
+ {
+ ContextHandler context=async.getContextHandler();
+ if (context!=null)
+ {
+ Handler branch = _contextBranches.get(context);
+
+ if (branch==null)
+ context.handle(target,baseRequest,request, response);
+ else
+ branch.handle(target, baseRequest, request, response);
+ return;
+ }
+ }
+
+ // data structure which maps a request to a context; first-best match wins
+ // { context path => [ context ] }
+ // }
+ if (target.startsWith("/"))
+ {
+ int limit = target.length()-1;
- int l=contexts[0].getContextPath().length();
- if (l==1 || target.length()==l || target.charAt(l)=='/')
- {
- for (ContextHandler handler : contexts)
- {
- handler.handle(target,baseRequest, request, response);
- if (baseRequest.isHandled())
- return;
- }
- }
-
- limit=l-2;
- }
- }
- else
- {
+ while (limit>=0)
+ {
+ // Get best match
+ Map.Entry<String,Branch[]> branches = _pathBranches.getBest(target,1,limit);
+
+
+ if (branches==null)
+ break;
+
+ int l=branches.getKey().length();
+ if (l==1 || target.length()==l || target.charAt(l)=='/')
+ {
+ for (Branch branch : branches.getValue())
+ {
+ branch.getHandler().handle(target,baseRequest, request, response);
+ if (baseRequest.isHandled())
+ return;
+ }
+ }
+
+ limit=l-2;
+ }
+ }
+ else
+ {
// This may not work in all circumstances... but then I think it should never be called
- for (int i=0;i<handlers.length;i++)
- {
- handlers[i].handle(target,baseRequest, request, response);
- if ( baseRequest.isHandled())
- return;
- }
- }
+ for (int i=0;i<handlers.length;i++)
+ {
+ handlers[i].handle(target,baseRequest, request, response);
+ if ( baseRequest.isHandled())
+ return;
+ }
+ }
}
-
/* ------------------------------------------------------------ */
/** Add a context handler.
* @param contextPath The context path to add
@@ -263,5 +278,64 @@ public class ContextHandlerCollection extends HandlerCollection
_contextClass = contextClass;
}
+ /* ------------------------------------------------------------ */
+ /* ------------------------------------------------------------ */
+ /* ------------------------------------------------------------ */
+ private final static class Branch
+ {
+ private final Handler _handler;
+ private final ContextHandler[] _contexts;
+
+ Branch(Handler handler)
+ {
+ _handler=handler;
+
+ if (handler instanceof ContextHandler)
+ {
+ _contexts = new ContextHandler[]{(ContextHandler)handler};
+ }
+ else if (handler instanceof HandlerContainer)
+ {
+ Handler[] contexts=((HandlerContainer)handler).getChildHandlersByClass(ContextHandler.class);
+ _contexts = new ContextHandler[contexts.length];
+ System.arraycopy(contexts, 0, _contexts, 0, contexts.length);
+ }
+ else
+ _contexts = new ContextHandler[0];
+ }
+
+ Set<String> getContextPaths()
+ {
+ Set<String> set = new HashSet<String>();
+ for (ContextHandler context:_contexts)
+ set.add(context.getContextPath());
+ return set;
+ }
+
+ boolean hasVirtualHost()
+ {
+ for (ContextHandler context:_contexts)
+ if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
+ return true;
+ return false;
+ }
+
+ ContextHandler[] getContextHandlers()
+ {
+ return _contexts;
+ }
+
+ Handler getHandler()
+ {
+ return _handler;
+ }
+
+ @Override
+ public String toString()
+ {
+ return String.format("{%s,%s}",_handler,Arrays.asList(_contexts));
+ }
+ }
+
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java
index f71720af41..cf92003c0e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java
@@ -117,62 +117,63 @@ public class DefaultHandler extends AbstractHandler
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
response.setContentType(MimeTypes.Type.TEXT_HTML.toString());
- ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(1500);
-
- writer.write("<HTML>\n<HEAD>\n<TITLE>Error 404 - Not Found");
- writer.write("</TITLE>\n<BODY>\n<H2>Error 404 - Not Found.</H2>\n");
- writer.write("No context on this server matched or handled this request.<BR>");
- writer.write("Contexts known to this server are: <ul>");
+ try (ByteArrayISO8859Writer writer = new ByteArrayISO8859Writer(1500);)
+ {
+ writer.write("<HTML>\n<HEAD>\n<TITLE>Error 404 - Not Found");
+ writer.write("</TITLE>\n<BODY>\n<H2>Error 404 - Not Found.</H2>\n");
+ writer.write("No context on this server matched or handled this request.<BR>");
+ writer.write("Contexts known to this server are: <ul>");
- Server server = getServer();
- Handler[] handlers = server==null?null:server.getChildHandlersByClass(ContextHandler.class);
+ Server server = getServer();
+ Handler[] handlers = server==null?null:server.getChildHandlersByClass(ContextHandler.class);
- for (int i=0;handlers!=null && i<handlers.length;i++)
- {
- ContextHandler context = (ContextHandler)handlers[i];
- if (context.isRunning())
- {
- writer.write("<li><a href=\"");
- if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
- writer.write("http://"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
- writer.write(context.getContextPath());
- if (context.getContextPath().length()>1 && context.getContextPath().endsWith("/"))
- writer.write("/");
- writer.write("\">");
- writer.write(context.getContextPath());
- if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
- writer.write("&nbsp;@&nbsp;"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
- writer.write("&nbsp;--->&nbsp;");
- writer.write(context.toString());
- writer.write("</a></li>\n");
- }
- else
+ for (int i=0;handlers!=null && i<handlers.length;i++)
{
- writer.write("<li>");
- writer.write(context.getContextPath());
- if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
- writer.write("&nbsp;@&nbsp;"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
- writer.write("&nbsp;--->&nbsp;");
- writer.write(context.toString());
- if (context.isFailed())
- writer.write(" [failed]");
- if (context.isStopped())
- writer.write(" [stopped]");
- writer.write("</li>\n");
+ ContextHandler context = (ContextHandler)handlers[i];
+ if (context.isRunning())
+ {
+ writer.write("<li><a href=\"");
+ if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
+ writer.write("http://"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
+ writer.write(context.getContextPath());
+ if (context.getContextPath().length()>1 && context.getContextPath().endsWith("/"))
+ writer.write("/");
+ writer.write("\">");
+ writer.write(context.getContextPath());
+ if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
+ writer.write("&nbsp;@&nbsp;"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
+ writer.write("&nbsp;--->&nbsp;");
+ writer.write(context.toString());
+ writer.write("</a></li>\n");
+ }
+ else
+ {
+ writer.write("<li>");
+ writer.write(context.getContextPath());
+ if (context.getVirtualHosts()!=null && context.getVirtualHosts().length>0)
+ writer.write("&nbsp;@&nbsp;"+context.getVirtualHosts()[0]+":"+request.getLocalPort());
+ writer.write("&nbsp;--->&nbsp;");
+ writer.write(context.toString());
+ if (context.isFailed())
+ writer.write(" [failed]");
+ if (context.isStopped())
+ writer.write(" [stopped]");
+ writer.write("</li>\n");
+ }
}
- }
- writer.write("</ul><hr>");
- writer.write("<a href=\"http://eclipse.org/jetty\"><img border=0 src=\"/favicon.ico\"/></a>&nbsp;");
- writer.write("<a href=\"http://eclipse.org/jetty\">Powered by Jetty:// Java Web Server</a><hr/>\n");
+ writer.write("</ul><hr>");
+ writer.write("<a href=\"http://eclipse.org/jetty\"><img border=0 src=\"/favicon.ico\"/></a>&nbsp;");
+ writer.write("<a href=\"http://eclipse.org/jetty\">Powered by Jetty:// Java Web Server</a><hr/>\n");
- writer.write("\n</BODY>\n</HTML>\n");
- writer.flush();
- response.setContentLength(writer.size());
- try (OutputStream out=response.getOutputStream())
- {
- writer.writeTo(out);
- }
+ writer.write("\n</BODY>\n</HTML>\n");
+ writer.flush();
+ response.setContentLength(writer.size());
+ try (OutputStream out=response.getOutputStream())
+ {
+ writer.writeTo(out);
+ }
+ }
}
/* ------------------------------------------------------------ */
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java
index c118c7ec1d..b79b75dc23 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java
@@ -19,6 +19,7 @@
package org.eclipse.jetty.server.handler;
import java.io.IOException;
+import java.util.Arrays;
import java.util.List;
import javax.servlet.ServletException;
@@ -185,4 +186,12 @@ public class HandlerCollection extends AbstractHandlerContainer
child.destroy();
super.destroy();
}
+
+ /* ------------------------------------------------------------ */
+ @Override
+ public String toString()
+ {
+ Handler[] handlers=getHandlers();
+ return super.toString()+(handlers==null?"[]":Arrays.asList(getHandlers()).toString());
+ }
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java
index dcbf6ff5d5..88226c951e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java
@@ -30,7 +30,6 @@ import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
-import org.eclipse.jetty.util.component.LifeCycle;
/* ------------------------------------------------------------ */
/** A <code>HandlerWrapper</code> acts as a {@link Handler} but delegates the {@link Handler#handle handle} method and
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java
index 1db4283bc6..7c3f2a3886 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java
@@ -308,15 +308,16 @@ public class ResourceHandler extends HandlerWrapper
{
if (_context==null)
return null;
- base=_context.getBaseResource();
- if (base==null)
- return null;
+ return _context.getResource(path);
}
try
{
path=URIUtil.canonicalPath(path);
- return base.addPath(path);
+ Resource r = base.addPath(path);
+ if (r!=null && r.getAlias()!=null && !_context.checkAlias(path, r))
+ return null;
+ return r;
}
catch(Exception e)
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java
index 93c9f86a57..9c948ae0e7 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ShutdownHandler.java
@@ -133,6 +133,7 @@ public class ShutdownHandler extends HandlerWrapper
}
}
+ @SuppressWarnings("resource")
private String getServerUrl()
{
NetworkConnector connector=null;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
index ec586ac09c..3bed6cda0c 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSession.java
@@ -397,7 +397,6 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
}
/* ------------------------------------------------------------ */
- @SuppressWarnings({ "unchecked" })
@Override
public Enumeration<String> getAttributeNames()
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java
index 1f966c5957..aa039081e6 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java
@@ -227,10 +227,10 @@ public abstract class AbstractSessionManager extends ContainerLifeCycle implemen
_context=ContextHandler.getCurrentContext();
_loader=Thread.currentThread().getContextClassLoader();
- if (_sessionIdManager==null)
+ final Server server=getSessionHandler().getServer();
+ synchronized (server)
{
- final Server server=getSessionHandler().getServer();
- synchronized (server)
+ if (_sessionIdManager==null)
{
_sessionIdManager=server.getSessionIdManager();
if (_sessionIdManager==null)
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java
index a17bc06f76..382b633b5c 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java
@@ -32,8 +32,6 @@ import java.util.Set;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
-import org.eclipse.jetty.server.SessionIdManager;
-
/* ------------------------------------------------------------ */
/**
* HashSessionIdManager. An in-memory implementation of the session ID manager.
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java
index 1effd32f94..53ccd6398e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionManager.java
@@ -19,7 +19,6 @@
package org.eclipse.jetty.server.session;
import java.io.DataInputStream;
-import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
@@ -34,10 +33,8 @@ import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
-import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
-import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.thread.ScheduledExecutorScheduler;
import org.eclipse.jetty.util.thread.Scheduler;
@@ -308,9 +305,9 @@ public class HashSessionManager extends AbstractSessionManager
_scavengePeriodMs=period;
- if (_timer!=null && (period!=old_period || _task==null))
+ synchronized (this)
{
- synchronized (this)
+ if (_timer!=null && (period!=old_period || _task==null))
{
if (_task!=null)
{
@@ -569,18 +566,22 @@ public class HashSessionManager extends AbstractSessionManager
{
File file = new File(_storeDir,idInCuster);
- FileInputStream in = null;
Exception error = null;
- try
+ if (!file.exists())
{
- if (file.exists())
+ if (LOG.isDebugEnabled())
{
- in = new FileInputStream(file);
- HashedSession session = restoreSession(in, null);
- addSession(session, false);
- session.didActivate();
- return session;
+ LOG.debug("Not loading: {}",file);
}
+ return null;
+ }
+
+ try (FileInputStream in = new FileInputStream(file))
+ {
+ HashedSession session = restoreSession(in,null);
+ addSession(session,false);
+ session.didActivate();
+ return session;
}
catch (Exception e)
{
@@ -588,8 +589,6 @@ public class HashSessionManager extends AbstractSessionManager
}
finally
{
- if (in != null) IO.close(in);
-
if (error != null)
{
if (isDeleteUnrestorableSessions() && file.exists() && file.getParentFile().equals(_storeDir) )
@@ -603,7 +602,10 @@ public class HashSessionManager extends AbstractSessionManager
}
}
else
- file.delete(); //delete successfully restored file
+ {
+ // delete successfully restored file
+ file.delete();
+ }
}
return null;
}
@@ -641,8 +643,10 @@ public class HashSessionManager extends AbstractSessionManager
if (session == null)
session = (HashedSession)newSession(created, accessed, clusterId);
+
session.setRequests(requests);
+ // Attributes
int size = di.readInt();
restoreSessionAttributes(di, size, session);
@@ -652,7 +656,7 @@ public class HashSessionManager extends AbstractSessionManager
int maxIdle = di.readInt();
session.setMaxInactiveInterval(maxIdle);
}
- catch (EOFException e)
+ catch (IOException e)
{
LOG.debug("No maxInactiveInterval persisted for session "+clusterId);
LOG.ignore(e);
@@ -661,12 +665,14 @@ public class HashSessionManager extends AbstractSessionManager
return session;
}
-
+
+ @SuppressWarnings("resource")
private void restoreSessionAttributes (InputStream is, int size, HashedSession session)
throws Exception
{
if (size>0)
{
+ // input stream should not be closed here
ClassLoadingObjectInputStream ois = new ClassLoadingObjectInputStream(is);
for (int i=0; i<size;i++)
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java
index d36e4277e4..9bfa84d989 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/HashedSession.java
@@ -145,24 +145,23 @@ public class HashedSession extends MemSession
throws Exception
{
File file = null;
- FileOutputStream fos = null;
if (!_saveFailed && _hashSessionManager._storeDir != null)
{
- try
+ file = new File(_hashSessionManager._storeDir, super.getId());
+ if (file.exists())
+ {
+ file.delete();
+ }
+
+ try(FileOutputStream fos = new FileOutputStream(file,false))
{
- file = new File(_hashSessionManager._storeDir, super.getId());
- if (file.exists())
- file.delete();
- file.createNewFile();
- fos = new FileOutputStream(file);
save(fos);
- IO.close(fos);
}
catch (Exception e)
{
saveFailed(); // We won't try again for this session
- if (fos != null) IO.close(fos);
- if (file != null) file.delete(); // No point keeping the file if we didn't save the whole session
+ if (file != null)
+ file.delete(); // No point keeping the file if we didn't save the whole session
throw e;
}
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java
index a70d48ecfe..535dc5f02e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java
@@ -778,10 +778,10 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
if (LOG.isDebugEnabled())
LOG.debug("Scavenging every "+_scavengeIntervalMs+" ms");
- //if (_timer!=null && (period!=old_period || _task==null))
- if (_scheduler != null && (period!=old_period || _task==null))
+ synchronized (this)
{
- synchronized (this)
+ //if (_timer!=null && (period!=old_period || _task==null))
+ if (_scheduler != null && (period!=old_period || _task==null))
{
if (_task!=null)
_task.cancel();
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
index fb4d7468c5..a84376b02a 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java
@@ -37,10 +37,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpSessionEvent;
-import javax.servlet.http.HttpSessionListener;
-
-import org.eclipse.jetty.server.SessionIdManager;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.session.JDBCSessionIdManager.SessionTableSchema;
import org.eclipse.jetty.util.ClassLoadingObjectInputStream;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java
index e85cc9e2ed..fc86f3de5f 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java
@@ -49,10 +49,12 @@ public class SessionHandler extends ScopedHandler
final static Logger LOG = Log.getLogger("org.eclipse.jetty.server.session");
public final static EnumSet<SessionTrackingMode> DEFAULT_TRACKING = EnumSet.of(SessionTrackingMode.COOKIE,SessionTrackingMode.URL);
-
- public static final Class[] SESSION_LISTENER_TYPES = new Class[] {HttpSessionAttributeListener.class,
- HttpSessionIdListener.class,
- HttpSessionListener.class};
+
+ @SuppressWarnings("unchecked")
+ public static final Class<? extends EventListener>[] SESSION_LISTENER_TYPES =
+ new Class[] {HttpSessionAttributeListener.class,
+ HttpSessionIdListener.class,
+ HttpSessionListener.class};
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java
index 506ff9e2ea..cb60e0627d 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/CheckReverseProxyHeadersTest.java
@@ -66,7 +66,7 @@ public class CheckReverseProxyHeadersTest
@Override
public void validate(HttpServletRequest request)
{
- assertEquals("::1", request.getServerName());
+ assertEquals("[::1]", request.getServerName());
assertEquals(80, request.getServerPort());
assertEquals("10.20.30.40", request.getRemoteAddr());
assertEquals("10.20.30.40", request.getRemoteHost());
@@ -84,7 +84,7 @@ public class CheckReverseProxyHeadersTest
@Override
public void validate(HttpServletRequest request)
{
- assertEquals("::1", request.getServerName());
+ assertEquals("[::1]", request.getServerName());
assertEquals(8888, request.getServerPort());
assertEquals("10.20.30.40", request.getRemoteAddr());
assertEquals("10.20.30.40", request.getRemoteHost());
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java
index 2794cfb1f9..6943f768ce 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/GracefulStopTest.java
@@ -30,6 +30,8 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.StdErrLog;
import org.hamcrest.Matchers;
import org.junit.Assert;
import org.junit.Before;
@@ -79,6 +81,35 @@ public class GracefulStopTest
Assert.assertThat(out,Matchers.containsString("200 OK"));
}
}
+
+ @Test
+ public void testGracefulTimout() throws Exception
+ {
+ server.setStopTimeout(100);
+ new Thread()
+ {
+ @Override
+ public void run()
+ {
+ try
+ {
+ TimeUnit.SECONDS.sleep(1);
+ server.stop();
+ }
+ catch (Exception e)
+ {
+ //e.printStackTrace();
+ }
+ }
+ }.start();
+
+ try(Socket socket = new Socket("localhost",server.getBean(NetworkConnector.class).getLocalPort());)
+ {
+ socket.getOutputStream().write("GET / HTTP/1.0\r\n\r\n".getBytes(StandardCharsets.ISO_8859_1));
+ String out = IO.toString(socket.getInputStream());
+ Assert.assertEquals("",out);
+ }
+ }
private static class TestHandler extends AbstractHandler
{
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java
index 96056fda5f..d582e578ce 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpConnectionTest.java
@@ -723,7 +723,6 @@ public class HttpConnectionTest
"12345\015\012"+
"0;\015\012\015\012");
offset = checkContains(response,offset,"HTTP/1.1 200");
- offset = checkContains(response,offset,"Allow: GET,POST,HEAD");
offset=0;
response=connector.getResponses("GET * HTTP/1.1\n"+
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java
index e2b4f213d3..58497def1b 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/HttpURITest.java
@@ -136,11 +136,11 @@ public class HttpURITest
/*33*/ {"/?abc=test",null, null, null,null,"/", null,"abc=test",null},
/*34*/ {"/#fragment",null, null, null,null,"/", null,null,"fragment"},
/*35*/ {"http://192.0.0.1:8080/","http","//192.0.0.1:8080","192.0.0.1","8080","/",null,null,null},
- /*36*/ {"http://[2001:db8::1]:8080/","http","//[2001:db8::1]:8080","2001:db8::1","8080","/",null,null,null},
- /*37*/ {"http://user@[2001:db8::1]:8080/","http","//user@[2001:db8::1]:8080","2001:db8::1","8080","/",null,null,null},
- /*38*/ {"http://[2001:db8::1]/","http","//[2001:db8::1]","2001:db8::1",null,"/",null,null,null},
+ /*36*/ {"http://[2001:db8::1]:8080/","http","//[2001:db8::1]:8080","[2001:db8::1]","8080","/",null,null,null},
+ /*37*/ {"http://user@[2001:db8::1]:8080/","http","//user@[2001:db8::1]:8080","[2001:db8::1]","8080","/",null,null,null},
+ /*38*/ {"http://[2001:db8::1]/","http","//[2001:db8::1]","[2001:db8::1]",null,"/",null,null,null},
/*39*/ {"//[2001:db8::1]:8080/",null,null,null,null,"//[2001:db8::1]:8080/",null,null,null},
- /*40*/ {"http://user@[2001:db8::1]:8080/","http","//user@[2001:db8::1]:8080","2001:db8::1","8080","/",null,null,null},
+ /*40*/ {"http://user@[2001:db8::1]:8080/","http","//user@[2001:db8::1]:8080","[2001:db8::1]","8080","/",null,null,null},
/*41*/ {"*",null,null,null,null,"*",null, null,null}
};
@@ -353,7 +353,7 @@ public class HttpURITest
{
/* 0*/ {" localhost:8080 ","localhost","8080"},
/* 1*/ {" 127.0.0.1:8080 ","127.0.0.1","8080"},
- /* 2*/ {" [127::0::0::1]:8080 ","127::0::0::1","8080"},
+ /* 2*/ {" [127::0::0::1]:8080 ","[127::0::0::1]","8080"},
/* 3*/ {" error ",null,null},
/* 4*/ {" http://localhost:8080/ ",null,null},
};
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java
index ca9d7999cb..21589a4442 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/NetworkTrafficListenerTest.java
@@ -41,7 +41,6 @@ import org.eclipse.jetty.io.NetworkTrafficListener;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.BufferUtil;
import org.junit.After;
-import org.junit.Ignore;
import org.junit.Test;
public class NetworkTrafficListenerTest
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java
index 1643bab762..bfb52afab0 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/PartialRFC2616Test.java
@@ -495,7 +495,6 @@ public class PartialRFC2616Test
"Host: localhost\n"+
"\n");
offset=checkContains(response,offset, "HTTP/1.1 200","200")+1;
- offset=checkContains(response,offset, "Allow: GET,POST,HEAD,OPTIONS","Allow")+1;
offset=0;
response=connector.getResponses("GET * HTTP/1.1\n"+
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
index e9ed6d78d6..ef8025c70e 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/RequestTest.java
@@ -65,7 +65,6 @@ import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StdErrLog;
import org.hamcrest.Matchers;
import org.junit.After;
-import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -486,7 +485,7 @@ public class RequestTest
assertThat(response,Matchers.containsString("200 OK"));
assertEquals("http://[::1]/",results.get(i++));
assertEquals("0.0.0.0",results.get(i++));
- assertEquals("::1",results.get(i++));
+ assertEquals("[::1]",results.get(i++));
assertEquals("80",results.get(i++));
@@ -500,7 +499,7 @@ public class RequestTest
assertThat(response,Matchers.containsString("200 OK"));
assertEquals("http://[::1]:8888/",results.get(i++));
assertEquals("0.0.0.0",results.get(i++));
- assertEquals("::1",results.get(i++));
+ assertEquals("[::1]",results.get(i++));
assertEquals("8888",results.get(i++));
@@ -516,7 +515,7 @@ public class RequestTest
assertThat(response,Matchers.containsString("200 OK"));
assertEquals("https://[::1]/",results.get(i++));
assertEquals("remote",results.get(i++));
- assertEquals("::1",results.get(i++));
+ assertEquals("[::1]",results.get(i++));
assertEquals("443",results.get(i++));
@@ -532,7 +531,7 @@ public class RequestTest
assertThat(response,Matchers.containsString("200 OK"));
assertEquals("https://[::1]:8888/",results.get(i++));
assertEquals("remote",results.get(i++));
- assertEquals("::1",results.get(i++));
+ assertEquals("[::1]",results.get(i++));
assertEquals("8888",results.get(i++));
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java
new file mode 100644
index 0000000000..03ee046aa8
--- /dev/null
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ServerConnectorTest.java
@@ -0,0 +1,197 @@
+//
+// ========================================================================
+// Copyright (c) 1995-2014 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.server;
+
+import static org.hamcrest.Matchers.*;
+import static org.junit.Assert.*;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.PrintWriter;
+import java.lang.reflect.Field;
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.Socket;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.nio.charset.StandardCharsets;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.io.ChannelEndPoint;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.server.handler.DefaultHandler;
+import org.eclipse.jetty.server.handler.HandlerList;
+import org.eclipse.jetty.util.IO;
+import org.junit.Test;
+
+public class ServerConnectorTest
+{
+ public static class ReuseInfoHandler extends AbstractHandler
+ {
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ response.setContentType("text/plain");
+
+ EndPoint endPoint = baseRequest.getHttpChannel().getEndPoint();
+ assertThat("Endpoint",endPoint,instanceOf(ChannelEndPoint.class));
+ ChannelEndPoint channelEndPoint = (ChannelEndPoint)endPoint;
+ Socket socket = channelEndPoint.getSocket();
+ ServerConnector connector = (ServerConnector)baseRequest.getHttpChannel().getConnector();
+
+ PrintWriter out = response.getWriter();
+ out.printf("connector.getReuseAddress() = %b%n",connector.getReuseAddress());
+
+ try
+ {
+ Field fld = connector.getClass().getDeclaredField("_reuseAddress");
+ assertThat("Field[_reuseAddress]",fld,notNullValue());
+ fld.setAccessible(true);
+ Object val = fld.get(connector);
+ out.printf("connector._reuseAddress() = %b%n",val);
+ }
+ catch (Throwable t)
+ {
+ t.printStackTrace(out);
+ }
+
+ out.printf("socket.getReuseAddress() = %b%n",socket.getReuseAddress());
+
+ baseRequest.setHandled(true);
+ }
+ }
+
+ private URI toServerURI(ServerConnector connector) throws URISyntaxException
+ {
+ String host = connector.getHost();
+ if (host == null)
+ {
+ host = "localhost";
+ }
+ int port = connector.getLocalPort();
+ return new URI(String.format("http://%s:%d/",host,port));
+ }
+
+ private String getResponse(URI uri) throws MalformedURLException, IOException
+ {
+ HttpURLConnection http = (HttpURLConnection)uri.toURL().openConnection();
+ assertThat("Valid Response Code",http.getResponseCode(),anyOf(is(200),is(404)));
+
+ try (InputStream in = http.getInputStream())
+ {
+ return IO.toString(in,StandardCharsets.UTF_8);
+ }
+ }
+
+ @Test
+ public void testReuseAddress_Default() throws Exception
+ {
+ Server server = new Server();
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(0);
+ server.addConnector(connector);
+
+ HandlerList handlers = new HandlerList();
+ handlers.addHandler(new ReuseInfoHandler());
+ handlers.addHandler(new DefaultHandler());
+
+ server.setHandler(handlers);
+
+ try
+ {
+ server.start();
+
+ URI uri = toServerURI(connector);
+ String response = getResponse(uri);
+ assertThat("Response",response,containsString("connector.getReuseAddress() = true"));
+ assertThat("Response",response,containsString("connector._reuseAddress() = true"));
+ assertThat("Response",response,containsString("socket.getReuseAddress() = true"));
+ }
+ finally
+ {
+ server.stop();
+ }
+ }
+
+ @Test
+ public void testReuseAddress_True() throws Exception
+ {
+ Server server = new Server();
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(0);
+ connector.setReuseAddress(true);
+ server.addConnector(connector);
+
+ HandlerList handlers = new HandlerList();
+ handlers.addHandler(new ReuseInfoHandler());
+ handlers.addHandler(new DefaultHandler());
+
+ server.setHandler(handlers);
+
+ try
+ {
+ server.start();
+
+ URI uri = toServerURI(connector);
+ String response = getResponse(uri);
+ assertThat("Response",response,containsString("connector.getReuseAddress() = true"));
+ assertThat("Response",response,containsString("connector._reuseAddress() = true"));
+ assertThat("Response",response,containsString("socket.getReuseAddress() = true"));
+ }
+ finally
+ {
+ server.stop();
+ }
+ }
+
+ @Test
+ public void testReuseAddress_False() throws Exception
+ {
+ Server server = new Server();
+ ServerConnector connector = new ServerConnector(server);
+ connector.setPort(0);
+ connector.setReuseAddress(false);
+ server.addConnector(connector);
+
+ HandlerList handlers = new HandlerList();
+ handlers.addHandler(new ReuseInfoHandler());
+ handlers.addHandler(new DefaultHandler());
+
+ server.setHandler(handlers);
+
+ try
+ {
+ server.start();
+
+ URI uri = toServerURI(connector);
+ String response = getResponse(uri);
+ assertThat("Response",response,containsString("connector.getReuseAddress() = false"));
+ assertThat("Response",response,containsString("connector._reuseAddress() = false"));
+ assertThat("Response",response,containsString("socket.getReuseAddress() = false"));
+ }
+ finally
+ {
+ server.stop();
+ }
+ }
+}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ShutdownMonitorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ShutdownMonitorTest.java
index bd02b034d8..0b02ee1b8a 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ShutdownMonitorTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ShutdownMonitorTest.java
@@ -26,43 +26,36 @@ import java.io.LineNumberReader;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
+import java.util.concurrent.TimeUnit;
import org.junit.Test;
/**
* ShutdownMonitorTest
- *
- *
- *
*/
public class ShutdownMonitorTest
{
-
-
@Test
- public void testShutdown ()
- throws Exception
+ public void testShutdown() throws Exception
{
-
- //test port and key assignment
+ // test port and key assignment
ShutdownMonitor.getInstance().setPort(0);
ShutdownMonitor.getInstance().setExitVm(false);
ShutdownMonitor.getInstance().start();
String key = ShutdownMonitor.getInstance().getKey();
int port = ShutdownMonitor.getInstance().getPort();
-
- //try starting a 2nd time (should be ignored)
- ShutdownMonitor.getInstance().start();
-
-
+
+ // try starting a 2nd time (should be ignored)
+ ShutdownMonitor.getInstance().start();
+
stop(port,key,true);
assertTrue(!ShutdownMonitor.getInstance().isAlive());
-
- //should be able to change port and key because it is stopped
+
+ // should be able to change port and key because it is stopped
ShutdownMonitor.getInstance().setPort(0);
- ShutdownMonitor.getInstance().setKey("foo");
+ ShutdownMonitor.getInstance().setKey("foo");
ShutdownMonitor.getInstance().start();
-
+
key = ShutdownMonitor.getInstance().getKey();
port = ShutdownMonitor.getInstance().getPort();
assertTrue(ShutdownMonitor.getInstance().isAlive());
@@ -71,41 +64,34 @@ public class ShutdownMonitorTest
assertTrue(!ShutdownMonitor.getInstance().isAlive());
}
-
- public void stop (int port, String key, boolean check)
- throws Exception
+ public void stop(int port, String key, boolean check) throws Exception
{
- Socket s = null;
-
- try
+ System.out.printf("Attempting stop to localhost:%d (%b)%n",port,check);
+ try (Socket s = new Socket(InetAddress.getByName("127.0.0.1"),port))
{
- //send stop command
- s = new Socket(InetAddress.getByName("127.0.0.1"),port);
-
- OutputStream out = s.getOutputStream();
- out.write((key + "\r\nstop\r\n").getBytes());
- out.flush();
-
- if (check)
+ // send stop command
+ try (OutputStream out = s.getOutputStream())
{
- //wait a little
- Thread.currentThread().sleep(600);
+ out.write((key + "\r\nstop\r\n").getBytes());
+ out.flush();
- //check for stop confirmation
- LineNumberReader lin = new LineNumberReader(new InputStreamReader(s.getInputStream()));
- String response;
- if ((response = lin.readLine()) != null)
+ if (check)
{
- assertEquals("Stopped", response);
+ // wait a little
+ TimeUnit.MILLISECONDS.sleep(600);
+
+ // check for stop confirmation
+ LineNumberReader lin = new LineNumberReader(new InputStreamReader(s.getInputStream()));
+ String response;
+ if ((response = lin.readLine()) != null)
+ {
+ assertEquals("Stopped",response);
+ }
+ else
+ throw new IllegalStateException("No stop confirmation");
}
- else
- throw new IllegalStateException("No stop confirmation");
}
}
- finally
- {
- if (s != null) s.close();
- }
}
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java
index 5e2adf2a2f..3c13fea0ae 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerCollectionTest.java
@@ -18,17 +18,24 @@
package org.eclipse.jetty.server.handler;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.endsWith;
+import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
+import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
@@ -84,9 +91,9 @@ public class ContextHandlerCollectionTest
c.addHandler(contextC);
HandlerList list = new HandlerList();
- list.addHandler(contextD);
list.addHandler(contextE);
list.addHandler(contextF);
+ list.addHandler(contextD);
c.addHandler(list);
server.setHandler(c);
@@ -132,18 +139,22 @@ public class ContextHandlerCollectionTest
handlerE.reset();
handlerF.reset();
- // System.err.printf("test %d %s@%s --> %s | %s%n",i,uri,host,connector.getName(),handler);
+ String t = String.format("test %d %s@%s --> %s | %s%n",i,uri,host,connector.getName(),handler);
String response = connector.getResponses("GET "+uri+" HTTP/1.0\nHost: "+host+"\n\n");
if (handler==null)
{
- Assert.assertThat(response,Matchers.containsString(" 302 "));
+ Assert.assertThat(t,response,Matchers.containsString(" 302 "));
}
- else if (!handler.isHandled())
+ else
{
- System.err.printf("FAILED %d %s@%s --> %s | %s%n",i,uri,host,connector.getName(),handler);
- System.err.println(response);
- Assert.fail();
+ assertThat(t,response,endsWith(handler.toString()));
+ if (!handler.isHandled())
+ {
+ System.err.printf("FAILED %s",t);
+ System.err.println(response);
+ Assert.fail();
+ }
}
}
@@ -260,8 +271,148 @@ public class ContextHandlerCollectionTest
assertEquals(wrapperB,AbstractHandlerContainer.findContainerOf(contextB,HandlerWrapper.class,handlerB));
}
+
+ @Test
+ public void testWrappedContext() throws Exception
+ {
+ Server server = new Server();
+ LocalConnector connector = new LocalConnector(server);
+ server.setConnectors(new Connector[] { connector });
+
+ ContextHandler root = new ContextHandler("/");
+ root.setHandler(new IsHandledHandler("root"));
+
+ ContextHandler left = new ContextHandler("/left");
+ left.setHandler(new IsHandledHandler("left"));
+
+ HandlerList centre = new HandlerList();
+ ContextHandler centreLeft = new ContextHandler("/leftcentre");
+ centreLeft.setHandler(new IsHandledHandler("left of centre"));
+ ContextHandler centreRight = new ContextHandler("/rightcentre");
+ centreRight.setHandler(new IsHandledHandler("right of centre"));
+ centre.setHandlers(new Handler[]{centreLeft,new WrappedHandler(centreRight)});
+
+ ContextHandler right = new ContextHandler("/right");
+ right.setHandler(new IsHandledHandler("right"));
+
+ ContextHandlerCollection contexts = new ContextHandlerCollection();
+ contexts.setHandlers(new Handler[]{root,left,centre,new WrappedHandler(right)});
+
+ server.setHandler(contexts);
+ server.start();
+
+ String response=connector.getResponses("GET / HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("root"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /foobar/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("root"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /left/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("left"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /leftcentre/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("left of centre"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /rightcentre/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("right of centre"));
+ assertThat(response, containsString("Wrapped: TRUE"));
+
+ response=connector.getResponses("GET /right/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("right"));
+ assertThat(response, containsString("Wrapped: TRUE"));
+ }
+ @Test
+ public void testAsyncWrappedContext() throws Exception
+ {
+ Server server = new Server();
+ LocalConnector connector = new LocalConnector(server);
+ server.setConnectors(new Connector[] { connector });
+
+ ContextHandler root = new ContextHandler("/");
+ root.setHandler(new AsyncHandler("root"));
+
+ ContextHandler left = new ContextHandler("/left");
+ left.setHandler(new AsyncHandler("left"));
+
+ HandlerList centre = new HandlerList();
+ ContextHandler centreLeft = new ContextHandler("/leftcentre");
+ centreLeft.setHandler(new AsyncHandler("left of centre"));
+ ContextHandler centreRight = new ContextHandler("/rightcentre");
+ centreRight.setHandler(new AsyncHandler("right of centre"));
+ centre.setHandlers(new Handler[]{centreLeft,new WrappedHandler(centreRight)});
+
+ ContextHandler right = new ContextHandler("/right");
+ right.setHandler(new AsyncHandler("right"));
+
+ ContextHandlerCollection contexts = new ContextHandlerCollection();
+ contexts.setHandlers(new Handler[]{root,left,centre,new WrappedHandler(right)});
+
+ server.setHandler(contexts);
+ server.start();
+
+ String response=connector.getResponses("GET / HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("root"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /foobar/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("root"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /left/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("left"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /leftcentre/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("left of centre"));
+ assertThat(response, not(containsString("Wrapped: TRUE")));
+
+ response=connector.getResponses("GET /rightcentre/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("right of centre"));
+ assertThat(response, containsString("Wrapped: ASYNC"));
+
+ response=connector.getResponses("GET /right/info HTTP/1.0\r\n\r\n");
+ assertThat(response, startsWith("HTTP/1.1 200 OK"));
+ assertThat(response, endsWith("right"));
+ assertThat(response, containsString("Wrapped: ASYNC"));
+ }
+
+
+ private static final class WrappedHandler extends HandlerWrapper
+ {
+ WrappedHandler(Handler handler)
+ {
+ setHandler(handler);
+ }
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ if (response.containsHeader("Wrapped"))
+ response.setHeader("Wrapped", "ASYNC");
+ else
+ response.setHeader("Wrapped", "TRUE");
+ super.handle(target, baseRequest, request, response);
+ }
+ }
+
+
private static final class IsHandledHandler extends AbstractHandler
{
private boolean handled;
@@ -298,5 +449,41 @@ public class ContextHandlerCollectionTest
}
+
+ private static final class AsyncHandler extends AbstractHandler
+ {
+ private final String name;
+
+ public AsyncHandler(String string)
+ {
+ name=string;
+ }
+
+ @Override
+ public void handle(String s, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ baseRequest.setHandled(true);
+
+ String n = (String)baseRequest.getAttribute("async");
+ if (n==null)
+ {
+ AsyncContext async=baseRequest.startAsync();
+ async.setTimeout(1000);
+ baseRequest.setAttribute("async", name);
+ async.dispatch();
+ }
+ else
+ {
+ response.getWriter().print(n);
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return name;
+ }
+ }
+
}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java
index ebd686d53d..a562c09591 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/session/HashSessionManagerTest.java
@@ -22,6 +22,7 @@ import java.io.File;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.toolchain.test.FS;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.log.Log;
@@ -33,24 +34,6 @@ import org.junit.Test;
public class HashSessionManagerTest
{
- @After
- public void enableStacks()
- {
- enableStacks(true);
- }
-
- @Before
- public void quietStacks()
- {
- enableStacks(false);
- }
-
- protected void enableStacks(boolean enabled)
- {
- StdErrLog log = (StdErrLog)Log.getLogger("org.eclipse.jetty.server.session");
- log.setHideStacks(!enabled);
- }
-
@Test
public void testDangerousSessionIdRemoval() throws Exception
{
@@ -78,7 +61,8 @@ public class HashSessionManagerTest
manager.setDeleteUnrestorableSessions(true);
manager.setLazyLoad(true);
File testDir = MavenTestingUtils.getTargetTestingDir("hashes");
- testDir.mkdirs();
+ FS.ensureEmpty(testDir);
+
manager.setStoreDirectory(testDir);
Assert.assertTrue(new File(testDir, "validFile.session").createNewFile());
@@ -88,7 +72,6 @@ public class HashSessionManagerTest
manager.getSession("validFile.session");
Assert.assertTrue("File shouldn't exist!", !new File(testDir,"validFile.session").exists());
-
}
@Test
@@ -116,7 +99,6 @@ public class HashSessionManagerTest
server.start();
manager.start();
-
HashedSession session = (HashedSession)manager.newHttpSession(new Request(null, null));
String sessionId = session.getId();
@@ -124,7 +106,7 @@ public class HashSessionManagerTest
session.setAttribute("two", new Integer(2));
//stop will persist sessions
- manager.setMaxInactiveInterval(30); //change max inactive interval for *new* sessions
+ manager.setMaxInactiveInterval(30); // change max inactive interval for *new* sessions
manager.stop();
Assert.assertTrue("File should exist!", new File(testDir, session.getId()).exists());
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java
index 6cc241a9b0..6c5addb60d 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SelectChannelServerSslTest.java
@@ -63,9 +63,9 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
@Override
public void testFullMethod() throws Exception
{
- // Don't run on Windows (buggy JVM)
- Assume.assumeTrue(!OS.IS_WINDOWS);
-
+ // Don't run on Windows (buggy JVM)
+ Assume.assumeTrue(!OS.IS_WINDOWS);
+
try
{
super.testFullMethod();
@@ -79,8 +79,8 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
@Override
public void testFullURI() throws Exception
{
- // Don't run on Windows (buggy JVM)
- Assume.assumeTrue(!OS.IS_WINDOWS);
+ // Don't run on Windows (buggy JVM)
+ Assume.assumeTrue(!OS.IS_WINDOWS);
try
{
super.testFullURI();

Back to the top