Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'jetty-server/src/main/java/org')
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java119
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java16
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java22
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HandlerContainer.java4
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpConnection.java120
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/HttpOutput.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/LocalConnector.java10
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/NCSARequestLog.java338
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Request.java50
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/RequestLog.java5
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Response.java62
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/Server.java97
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/SessionIdManager.java11
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/SessionManager.java29
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java7
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/bio/SocketConnector.java81
-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.java491
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandlerCollection.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/DefaultHandler.java85
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java8
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java4
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerList.java6
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java348
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java847
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java23
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ResourceHandler.java68
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java10
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/nio/BlockingChannelConnector.java12
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/nio/SelectChannelConnector.java59
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/AbstractSessionManager.java107
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/HashSessionIdManager.java19
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionIdManager.java8
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/JDBCSessionManager.java22
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/session/SessionHandler.java8
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java2
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java7
-rw-r--r--jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSocketConnector.java48
38 files changed, 2249 insertions, 914 deletions
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 76064c4656..7fed43a9a1 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
@@ -68,15 +68,10 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
private boolean _useDNS;
private boolean _forwarded;
private String _hostHeader;
- private String _forwardedHostHeader = "X-Forwarded-Host"; // default to
- // mod_proxy_http
- // header
- private String _forwardedServerHeader = "X-Forwarded-Server"; // default to
- // mod_proxy_http
- // header
- private String _forwardedForHeader = "X-Forwarded-For"; // default to
- // mod_proxy_http
- // header
+
+ private String _forwardedHostHeader = "X-Forwarded-Host";
+ private String _forwardedServerHeader = "X-Forwarded-Server";
+ private String _forwardedForHeader = "X-Forwarded-For";
private boolean _reuseAddress = true;
protected int _maxIdleTime = 200000;
@@ -87,101 +82,70 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
private final AtomicLong _statsStartedAt = new AtomicLong(-1L);
- private final CounterStatistic _connectionStats = new CounterStatistic(); // connections
- // to
- // server
- private final SampleStatistic _requestStats = new SampleStatistic(); // requests
- // per
- // connection
- private final SampleStatistic _connectionDurationStats = new SampleStatistic(); // duration
- // of
- // a
- // connection
+ /** connections to server */
+ private final CounterStatistic _connectionStats = new CounterStatistic();
+ /** requests per connection */
+ private final SampleStatistic _requestStats = new SampleStatistic();
+ /** duration of a connection */
+ private final SampleStatistic _connectionDurationStats = new SampleStatistic();
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
/**
*/
public AbstractConnector()
{
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
public final Buffer newBuffer(int size)
{
// TODO remove once no overrides established
return null;
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
@Override
public Buffer newRequestBuffer(int size)
{
return new ByteArrayBuffer(size);
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
@Override
public Buffer newRequestHeader(int size)
{
return new ByteArrayBuffer(size);
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
@Override
public Buffer newResponseBuffer(int size)
{
return new ByteArrayBuffer(size);
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
@Override
public Buffer newResponseHeader(int size)
{
return new ByteArrayBuffer(size);
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
@Override
protected boolean isRequestHeader(Buffer buffer)
{
return true;
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
@Override
protected boolean isResponseHeader(Buffer buffer)
{
return true;
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
/*
*/
public Server getServer()
@@ -189,19 +153,13 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
return _server;
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
public void setServer(Server server)
{
_server = server;
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.http.HttpListener#getHttpServer()
*/
@@ -210,19 +168,13 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
return _threadPool;
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
public void setThreadPool(ThreadPool pool)
{
_threadPool = pool;
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
/**
*/
public void setHost(String host)
@@ -230,10 +182,7 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
_host = host;
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
/*
*/
public String getHost()
@@ -241,10 +190,7 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
return _host;
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.server.HttpListener#setPort(int)
*/
@@ -253,10 +199,7 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
_port = port;
}
- /*
- * --------------------------------------------------------------------------
- * -----
- */
+ /* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.server.HttpListener#getPort()
*/
@@ -490,8 +433,6 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
try
{
socket.setTcpNoDelay(true);
- if (_maxIdleTime >= 0)
- socket.setSoTimeout(_maxIdleTime);
if (_soLingerTime >= 0)
socket.setSoLinger(true,_soLingerTime / 1000);
else
@@ -777,7 +718,7 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
/* ------------------------------------------------------------ */
/**
- * @param forwardedHostHeader
+ * @param forwardedServerHeader
* The header name for forwarded server (default
* x-forwarded-server)
*/
@@ -794,12 +735,12 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
/* ------------------------------------------------------------ */
/**
- * @param forwardedHostHeader
+ * @param forwardedRemoteAddressHeader
* The header name for forwarded for (default x-forwarded-for)
*/
- public void setForwardedForHeader(String forwardedRemoteAddressHeade)
+ public void setForwardedForHeader(String forwardedRemoteAddressHeader)
{
- _forwardedForHeader = forwardedRemoteAddressHeade;
+ _forwardedForHeader = forwardedRemoteAddressHeader;
}
/* ------------------------------------------------------------ */
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java
index b4ead4ad3b..5aad13129a 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncContinuation.java
@@ -672,7 +672,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
{
_expireAt = System.currentTimeMillis()+_timeoutMs;
long wait=_timeoutMs;
- while (_expireAt>0 && wait>0)
+ while (_expireAt>0 && wait>0 && _connection.getServer().isRunning())
{
try
{
@@ -685,7 +685,7 @@ public class AsyncContinuation implements AsyncContext, Continuation
wait=_expireAt-System.currentTimeMillis();
}
- if (_expireAt>0 && wait<=0)
+ if (_expireAt>0 && wait<=0 && _connection.getServer().isRunning())
{
expired();
}
@@ -823,11 +823,19 @@ public class AsyncContinuation implements AsyncContext, Continuation
}
/* ------------------------------------------------------------ */
- public void start(Runnable run)
+ public void start(final Runnable run)
{
final AsyncEventState event=_event;
if (event!=null)
- ((Context)event.getServletContext()).getContextHandler().handle(run);
+ {
+ _connection.getServer().getThreadPool().dispatch(new Runnable()
+ {
+ public void run()
+ {
+ ((Context)event.getServletContext()).getContextHandler().handle(run);
+ }
+ });
+ }
}
/* ------------------------------------------------------------ */
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 5328a1a143..5a77634e0a 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
@@ -131,14 +131,14 @@ public interface Connector extends LifeCycle
/* ------------------------------------------------------------ */
/**
* @return The port to use when redirecting a request if a data constraint of integral is
- * required. See {@link org.eclipse.jetty.server.server.security.Constraint#getDataConstraint()}
+ * required. See {@link org.eclipse.jetty.http.security.Constraint#getDataConstraint()}
*/
int getIntegralPort();
/* ------------------------------------------------------------ */
/**
* @return The schema to use when redirecting a request if a data constraint of integral is
- * required. See {@link org.eclipse.jetty.server.server.security.Constraint#getDataConstraint()}
+ * required. See {@link org.eclipse.jetty.http.security.Constraint#getDataConstraint()}
*/
String getIntegralScheme();
@@ -152,7 +152,7 @@ public interface Connector extends LifeCycle
/* ------------------------------------------------------------ */
/**
* @return The port to use when redirecting a request if a data constraint of confidential is
- * required. See {@link org.eclipse.jetty.server.server.security.Constraint#getDataConstraint()}
+ * required. See {@link org.eclipse.jetty.http.security.Constraint#getDataConstraint()}
*/
int getConfidentialPort();
@@ -160,7 +160,7 @@ public interface Connector extends LifeCycle
/* ------------------------------------------------------------ */
/**
* @return The schema to use when redirecting a request if a data constraint of confidential is
- * required. See {@link org.eclipse.jetty.server.server.security.Constraint#getDataConstraint()}
+ * required. See {@link org.eclipse.jetty.http.security.Constraint#getDataConstraint()}
*/
String getConfidentialScheme();
@@ -185,15 +185,23 @@ public interface Connector extends LifeCycle
/** Persist an endpoint.
* Called after every request if the connection is to remain open.
* @param endpoint
- * @param request
* @throws IOException
*/
void persist(EndPoint endpoint) throws IOException;
/* ------------------------------------------------------------ */
+ /**
+ * @return The hostname representing the interface to which
+ * this connector will bind, or null for all interfaces.
+ */
String getHost();
/* ------------------------------------------------------------ */
+ /**
+ * Set the hostname of the interface to bind to.
+ * @param hostname The hostname representing the interface to which
+ * this connector will bind, or null for all interfaces.
+ */
void setHost(String hostname);
/* ------------------------------------------------------------ */
@@ -212,8 +220,8 @@ public interface Connector extends LifeCycle
/* ------------------------------------------------------------ */
/**
- * @return The actual port the connector is listening on or -1 if there
- * is no port or the connector is not open.
+ * @return The actual port the connector is listening on or
+ * -1 if it has not been opened, or -2 if it has been closed.
*/
int getLocalPort();
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/HandlerContainer.java b/jetty-server/src/main/java/org/eclipse/jetty/server/HandlerContainer.java
index a64c0f8d0b..32406ce3f4 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/HandlerContainer.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/HandlerContainer.java
@@ -18,8 +18,8 @@ import org.eclipse.jetty.util.component.LifeCycle;
/**
* A Handler that contains other Handlers.
* <p>
- * The contained handlers may be one (see @{link {@link org.eclipse.jetty.server.server.handler.HandlerWrapper})
- * or many (see {@link org.eclipse.jetty.server.server.handler.HandlerList} or {@link org.eclipse.jetty.server.server.handler.HandlerCollection}.
+ * The contained handlers may be one (see @{link {@link org.eclipse.jetty.server.handler.HandlerWrapper})
+ * or many (see {@link org.eclipse.jetty.server.handler.HandlerList} or {@link org.eclipse.jetty.server.handler.HandlerCollection}.
*
*/
public interface HandlerContainer extends LifeCycle
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 c85638b9cc..8c71df016c 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
@@ -16,7 +16,6 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
-
import javax.servlet.DispatcherType;
import javax.servlet.ServletInputStream;
import javax.servlet.ServletOutputStream;
@@ -42,13 +41,12 @@ import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http.Parser;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
+import org.eclipse.jetty.io.BufferCache.CachedBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.UncheckedIOException;
import org.eclipse.jetty.io.UncheckedPrintWriter;
-import org.eclipse.jetty.io.BufferCache.CachedBuffer;
-import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
@@ -69,7 +67,7 @@ import org.eclipse.jetty.util.thread.Timeout;
* with the connection via the parser and/or generator.
* </p>
* <p>
- * The connection state is held by 3 separate state machines: The request state, the
+ * The connection state is held by 3 separate state machines: The request state, the
* response state and the continuation state. All three state machines must be driven
* to completion for every request, and all three can complete in any order.
* </p>
@@ -77,12 +75,12 @@ import org.eclipse.jetty.util.thread.Timeout;
* The HttpConnection support protocol upgrade. If on completion of a request, the
* response code is 101 (switch protocols), then the org.eclipse.jetty.io.Connection
* request attribute is checked to see if there is a new Connection instance. If so,
- * the new connection is returned from {@link #handle()} and is used for future
+ * the new connection is returned from {@link #handle()} and is used for future
* handling of the underlying connection. Note that for switching protocols that
* don't use 101 responses (eg CONNECT), the response should be sent and then the
- * status code changed to 101 before returning from the handler. Implementors
+ * status code changed to 101 before returning from the handler. Implementors
* of new Connection types should be careful to extract any buffered data from
- * (HttpParser)http.getParser()).getHeaderBuffer() and
+ * (HttpParser)http.getParser()).getHeaderBuffer() and
* (HttpParser)http.getParser()).getBodyBuffer() to initialise their new connection.
* </p>
*
@@ -150,7 +148,7 @@ public class HttpConnection implements Connection
HttpBuffers ab = (HttpBuffers)_connector;
_parser = new HttpParser(ab.getRequestBuffers(), endpoint, new RequestHandler());
_requestFields = new HttpFields();
- _responseFields = new HttpFields();
+ _responseFields = new HttpFields(server.getMaxCookieVersion());
_request = new Request(this);
_response = new Response(this);
_generator = new HttpGenerator(ab.getResponseBuffers(), _endp);
@@ -167,7 +165,7 @@ public class HttpConnection implements Connection
_endp = endpoint;
_parser = parser;
_requestFields = new HttpFields();
- _responseFields = new HttpFields();
+ _responseFields = new HttpFields(server.getMaxCookieVersion());
_request = request;
_response = new Response(this);
_generator = generator;
@@ -192,7 +190,13 @@ public class HttpConnection implements Connection
{
return _requests;
}
-
+
+ /* ------------------------------------------------------------ */
+ public Server getServer()
+ {
+ return _server;
+ }
+
/* ------------------------------------------------------------ */
/**
* @return The time this connection was established.
@@ -378,6 +382,8 @@ public class HttpConnection implements Connection
/* ------------------------------------------------------------ */
public Connection handle() throws IOException
{
+ Connection connection = this;
+
// Loop while more in buffer
boolean more_in_buffer =true; // assume true until proven otherwise
boolean progress=true;
@@ -389,12 +395,15 @@ public class HttpConnection implements Connection
_handling=true;
setCurrentConnection(this);
- while (more_in_buffer)
+ while (more_in_buffer && _endp.isOpen())
{
try
{
if (_request._async.isAsync())
{
+ // TODO - handle the case of input being read for a
+ // suspended request.
+
Log.debug("async request",_request);
if (!_request._async.isComplete())
handleRequest();
@@ -454,38 +463,44 @@ public class HttpConnection implements Connection
_parser.reset(true);
_endp.close();
- throw e;
}
finally
{
more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
+ // Is this request/response round complete?
if (_parser.isComplete() && _generator.isComplete() && !_endp.isBufferingOutput())
{
- if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
+ // look for a switched connection instance?
+ Connection switched=(_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
+ ?(Connection)_request.getAttribute("org.eclipse.jetty.io.Connection"):null;
+
+ // have we switched?
+ if (switched!=null)
{
- Connection connection = (Connection)_request.getAttribute("org.eclipse.jetty.io.Connection");
- if (connection!=null)
+ _parser.reset(true);
+ _generator.reset(true);
+ connection=switched;
+ }
+ else
+ {
+ // No switch, so cleanup and reset
+ if (!_generator.isPersistent())
{
_parser.reset(true);
- return connection;
+ more_in_buffer=false;
+ _endp.close();
}
- }
-
- if (!_generator.isPersistent())
- {
- _parser.reset(true);
- more_in_buffer=false;
- }
- if (more_in_buffer)
- {
- reset(false);
- more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
+ if (more_in_buffer)
+ {
+ reset(false);
+ more_in_buffer = _parser.isMoreInBuffer() || _endp.isBufferingInput();
+ }
+ else
+ reset(true);
+ progress=true;
}
- else
- reset(true);
- progress=true;
}
if (_request.isAsyncStarted())
@@ -493,7 +508,7 @@ public class HttpConnection implements Connection
Log.debug("return with suspended request");
more_in_buffer=false;
}
- else if (_generator.isCommitted() && !_generator.isComplete() && _endp instanceof AsyncEndPoint)
+ else if (_generator.isCommitted() && !_generator.isComplete() && _endp instanceof AsyncEndPoint)
((AsyncEndPoint)_endp).setWritable(false);
}
}
@@ -503,7 +518,7 @@ public class HttpConnection implements Connection
setCurrentConnection(null);
_handling=false;
}
- return this;
+ return connection;
}
/* ------------------------------------------------------------ */
@@ -567,7 +582,7 @@ public class HttpConnection implements Connection
{
_uri.getPort();
info=URIUtil.canonicalPath(_uri.getDecodedPath());
- if (info==null)
+ if (info==null && !_request.getMethod().equals(HttpMethods.CONNECT))
throw new HttpException(400);
_request.setPathInfo(info);
@@ -623,7 +638,6 @@ public class HttpConnection implements Connection
Log.debug(e);
_request.setHandled(true);
_generator.sendError(info==null?400:500, null, null, true);
-
}
finally
{
@@ -683,6 +697,10 @@ public class HttpConnection implements Connection
_generator.setResponse(_response.getStatus(), _response.getReason());
try
{
+ // If the client was expecting 100 continues, but we sent something
+ // else, then we need to close the connection
+ if (_expect100Continue && _response.getStatus()!=100)
+ _generator.setPersistent(false);
_generator.completeHeader(_responseFields, last);
}
catch(IOException io)
@@ -832,7 +850,20 @@ public class HttpConnection implements Connection
try
{
- _uri.parse(uri.array(), uri.getIndex(), uri.length());
+ switch (HttpMethods.CACHE.getOrdinal(method))
+ {
+ case HttpMethods.CONNECT_ORDINAL:
+ _uri.parseConnect(uri.array(), uri.getIndex(), uri.length());
+ break;
+
+ case HttpMethods.HEAD_ORDINAL:
+ _head=true;
+ // fall through
+
+ default:
+ _uri.parse(uri.array(), uri.getIndex(), uri.length());
+ }
+
_request.setUri(_uri);
if (version==null)
@@ -847,8 +878,6 @@ public class HttpConnection implements Connection
if (_version <= 0) _version = HttpVersions.HTTP_1_0_ORDINAL;
_request.setProtocol(version.toString());
}
-
- _head = method == HttpMethods.HEAD_BUFFER; // depends on method being decached.
}
catch (Exception e)
{
@@ -968,6 +997,8 @@ public class HttpConnection implements Connection
@Override
public void headerComplete() throws IOException
{
+ if (_endp instanceof AsyncEndPoint)
+ ((AsyncEndPoint)_endp).scheduleIdle();
_requests++;
_generator.setVersion(_version);
switch (_version)
@@ -976,6 +1007,10 @@ public class HttpConnection implements Connection
break;
case HttpVersions.HTTP_1_0_ORDINAL:
_generator.setHead(_head);
+
+ if (_server.getSendDateHeader())
+ _generator.setDate(_request.getTimeStampBuffer());
+
break;
case HttpVersions.HTTP_1_1_ORDINAL:
_generator.setHead(_head);
@@ -994,7 +1029,10 @@ public class HttpConnection implements Connection
if (_expect)
{
- _generator.sendError(HttpStatus.EXPECTATION_FAILED_417, null, null, true);
+ _generator.setResponse(HttpStatus.EXPECTATION_FAILED_417, null);
+ _responseFields.put(HttpHeaders.CONNECTION_BUFFER, HttpHeaderValues.CLOSE_BUFFER);
+ _generator.completeHeader(_responseFields, true);
+ _generator.complete();
return;
}
@@ -1019,6 +1057,8 @@ public class HttpConnection implements Connection
@Override
public void content(Buffer ref) throws IOException
{
+ if (_endp instanceof AsyncEndPoint)
+ ((AsyncEndPoint)_endp).scheduleIdle();
if (_delayedHandling)
{
_delayedHandling=false;
@@ -1148,13 +1188,13 @@ public class HttpConnection implements Connection
else
{
_responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
- contentType+";charset="+QuotedStringTokenizer.quote(enc,";= "));
+ contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(enc,";= "));
}
}
else
{
_responseFields.put(HttpHeaders.CONTENT_TYPE_BUFFER,
- contentType+";charset="+QuotedStringTokenizer.quote(enc,";= "));
+ contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(enc,";= "));
}
}
}
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 403c29d803..e7190a7b19 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
@@ -28,7 +28,7 @@ import org.eclipse.jetty.util.ByteArrayOutputStream2;
/** Output.
*
* <p>
- * Implements {@link javax.servlet.ServletOutputStream} from the {@link javax.servlet} package.
+ * Implements {@link javax.servlet.ServletOutputStream} from the <code>javax.servlet</code> package.
* </p>
* A {@link ServletOutputStream} implementation that writes content
* to a {@link AbstractGenerator}. The class is designed to be reused
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 6385d2785a..30267c2a46 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
@@ -33,14 +33,6 @@ public class LocalConnector extends AbstractConnector
return this;
}
- /**
- * @deprecated Not needed anymore, as there is no need to reopen the connector to reset its state
- */
- @Deprecated
- public void reopen()
- {
- }
-
public String getResponses(String requests) throws Exception
{
return getResponses(requests, false);
@@ -121,7 +113,7 @@ public class LocalConnector extends AbstractConnector
boolean leaveOpen = keepOpen;
try
{
- while (endPoint.getIn().length() > 0)
+ while (endPoint.getIn().length() > 0 && endPoint.isOpen())
{
while (true)
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/NCSARequestLog.java b/jetty-server/src/main/java/org/eclipse/jetty/server/NCSARequestLog.java
index 5a19545b10..f90e7818fc 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/NCSARequestLog.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/NCSARequestLog.java
@@ -4,11 +4,11 @@
// 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
+// 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.
+// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server;
@@ -20,7 +20,6 @@ import java.io.Writer;
import java.util.ArrayList;
import java.util.Locale;
import java.util.TimeZone;
-
import javax.servlet.http.Cookie;
import org.eclipse.jetty.http.HttpHeaders;
@@ -28,7 +27,6 @@ import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.RolloverFileOutputStream;
import org.eclipse.jetty.util.StringUtil;
-import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.Utf8StringBuilder;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log;
@@ -40,12 +38,13 @@ import org.eclipse.jetty.util.log.Log;
* Format (single log format). This log format can be output by most web
* servers, and almost all web log analysis software can understand these
* formats.
- *
- *
- *
- *
+ *
* @org.apache.xbean.XBean element="ncsaLog"
*/
+
+/* ------------------------------------------------------------ */
+/**
+ */
public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
{
private String _filename;
@@ -62,6 +61,7 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
private boolean _logLatency = false;
private boolean _logCookies = false;
private boolean _logServer = false;
+ private boolean _logDispatch = false;
private transient OutputStream _out;
private transient OutputStream _fileOut;
@@ -71,6 +71,10 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
private transient ArrayList _buffers;
private transient char[] _copy;
+ /* ------------------------------------------------------------ */
+ /**
+ * Create request log object with default settings.
+ */
public NCSARequestLog()
{
_extended = true;
@@ -80,9 +84,11 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
/* ------------------------------------------------------------ */
/**
- * @param filename
- * The filename for the request log. This may be in the
- * format expected by {@link RolloverFileOutputStream}
+ * Create request log object with specified output file name.
+ *
+ * @param filename the file name for the request log.
+ * This may be in the format expected
+ * by {@link RolloverFileOutputStream}
*/
public NCSARequestLog(String filename)
{
@@ -94,9 +100,12 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
/* ------------------------------------------------------------ */
/**
- * @param filename
- * The filename for the request log. This may be in the
- * format expected by {@link RolloverFileOutputStream}
+ * Set the output file name of the request log.
+ * The file name may be in the format expected by
+ * {@link RolloverFileOutputStream}.
+ *
+ * @param filename file name of the request log
+ *
*/
public void setFilename(String filename)
{
@@ -109,11 +118,25 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
_filename = filename;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve the output file name of the request log.
+ *
+ * @return file name of the request log
+ */
public String getFilename()
{
return _filename;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve the file name of the request log with the expanded
+ * date wildcard if the output is written to the disk using
+ * {@link RolloverFileOutputStream}.
+ *
+ * @return file name of the request log, or null if not applicable
+ */
public String getDatedFilename()
{
if (_fileOut instanceof RolloverFileOutputStream)
@@ -123,116 +146,306 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
/* ------------------------------------------------------------ */
/**
- * @param format
- * Format for the timestamps in the log file. If not set, the
- * pre-formated request timestamp is used.
+ * Set the timestamp format for request log entries in the file.
+ * If this is not set, the pre-formated request timestamp is used.
+ *
+ * @param format timestamp format string
*/
public void setLogDateFormat(String format)
{
_logDateFormat = format;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve the timestamp format string for request log entries.
+ *
+ * @return timestamp format string.
+ */
public String getLogDateFormat()
{
return _logDateFormat;
}
-
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Set the locale of the request log.
+ *
+ * @param logLocale locale object
+ */
public void setLogLocale(Locale logLocale)
{
_logLocale = logLocale;
}
-
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve the locale of the request log.
+ *
+ * @return locale object
+ */
public Locale getLogLocale()
{
return _logLocale;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Set the timezone of the request log.
+ *
+ * @param tz timezone string
+ */
public void setLogTimeZone(String tz)
{
_logTimeZone = tz;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve the timezone of the request log.
+ *
+ * @return timezone string
+ */
public String getLogTimeZone()
{
return _logTimeZone;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Set the number of days before rotated log files are deleted.
+ *
+ * @param retainDays number of days to keep a log file
+ */
public void setRetainDays(int retainDays)
{
_retainDays = retainDays;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve the number of days before rotated log files are deleted.
+ *
+ * @return number of days to keep a log file
+ */
public int getRetainDays()
{
return _retainDays;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Set the extended request log format flag.
+ *
+ * @param extended true - log the extended request information,
+ * false - do not log the extended request information
+ */
public void setExtended(boolean extended)
{
_extended = extended;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve the extended request log format flag.
+ *
+ * @return value of the flag
+ */
public boolean isExtended()
{
return _extended;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Set append to log flag.
+ *
+ * @param append true - request log file will be appended after restart,
+ * false - request log file will be overwritten after restart
+ */
public void setAppend(boolean append)
{
_append = append;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve append to log flag.
+ *
+ * @return value of the flag
+ */
public boolean isAppend()
{
return _append;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Set request paths that will not be logged.
+ *
+ * @param ignorePaths array of request paths
+ */
public void setIgnorePaths(String[] ignorePaths)
{
_ignorePaths = ignorePaths;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve the request paths that will not be logged.
+ *
+ * @return array of request paths
+ */
public String[] getIgnorePaths()
{
return _ignorePaths;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Controls logging of the request cookies.
+ *
+ * @param logCookies true - values of request cookies will be logged,
+ * false - values of request cookies will not be logged
+ */
public void setLogCookies(boolean logCookies)
{
_logCookies = logCookies;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve log cookies flag
+ *
+ * @return value of the flag
+ */
public boolean getLogCookies()
{
return _logCookies;
}
- public boolean getLogServer()
+ /* ------------------------------------------------------------ */
+ /**
+ * Controls logging of the request hostname.
+ *
+ * @param logServer true - request hostname will be logged,
+ * false - request hostname will not be logged
+ */
+ public void setLogServer(boolean logServer)
{
- return _logServer;
+ _logServer = logServer;
}
- public void setLogServer(boolean logServer)
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve log hostname flag.
+ *
+ * @return value of the flag
+ */
+ public boolean getLogServer()
{
- _logServer = logServer;
+ return _logServer;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Controls logging of request processing time.
+ *
+ * @param logLatency true - request processing time will be logged
+ * false - request processing time will not be logged
+ */
public void setLogLatency(boolean logLatency)
{
_logLatency = logLatency;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve log request processing time flag.
+ *
+ * @return value of the flag
+ */
public boolean getLogLatency()
{
return _logLatency;
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Controls whether the actual IP address of the connection or
+ * the IP address from the X-Forwarded-For header will be logged.
+ *
+ * @param preferProxiedForAddress true - IP address from header will be logged,
+ * false - IP address from the connection will be logged
+ */
public void setPreferProxiedForAddress(boolean preferProxiedForAddress)
{
_preferProxiedForAddress = preferProxiedForAddress;
}
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieved log X-Forwarded-For IP address flag.
+ *
+ * @return value of the flag
+ */
+ public boolean getPreferProxiedForAddress()
+ {
+ return _preferProxiedForAddress;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Set the log file name date format.
+ * @see RolloverFileOutputStream#RolloverFileOutputStream(String, boolean, int, TimeZone, String, String)
+ *
+ * @param logFileDateFormat format string that is passed to {@link RolloverFileOutputStream}
+ */
+ public void setFilenameDateFormat(String logFileDateFormat)
+ {
+ _filenameDateFormat = logFileDateFormat;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve the file name date format string.
+ *
+ * @return the log File Date Format
+ */
+ public String getFilenameDateFormat()
+ {
+ return _filenameDateFormat;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Controls logging of the request dispatch time
+ *
+ * @param value true - request dispatch time will be logged
+ * false - request dispatch time will not be logged
+ */
+ public void setLogDispatch(boolean value)
+ {
+ _logDispatch = value;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Retrieve request dispatch time logging flag
+ *
+ * @return value of the flag
+ */
+ public boolean isLogDispatch()
+ {
+ return _logDispatch;
+ }
/* ------------------------------------------------------------ */
+ /**
+ * Writes the request and response information to the output stream.
+ *
+ * @see org.eclipse.jetty.server.RequestLog#log(org.eclipse.jetty.server.Request, org.eclipse.jetty.server.Response)
+ */
public void log(Request request, Response response)
{
if (!isStarted())
@@ -254,7 +467,7 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
u8buf = size==0?new Utf8StringBuilder(160):(Utf8StringBuilder)_buffers.remove(size-1);
buf = u8buf.getStringBuilder();
}
-
+
if (_logServer)
{
buf.append(request.getServerName());
@@ -277,7 +490,7 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
buf.append(((Authentication.User)authentication).getUserIdentity().getUserPrincipal().getName());
else
buf.append(" - ");
-
+
buf.append(" [");
if (_logDateCache != null)
buf.append(_logDateCache.format(request.getTimeStamp()));
@@ -335,12 +548,12 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
buf.append(StringUtil.__LINE_SEPARATOR);
int l=buf.length();
if (l>_copy.length)
- l=_copy.length;
- buf.getChars(0,l,_copy,0);
+ l=_copy.length;
+ buf.getChars(0,l,_copy,0);
_writer.write(_copy,0,l);
_writer.flush();
u8buf.reset();
- _buffers.add(u8buf);
+ _buffers.add(u8buf);
}
}
else
@@ -349,11 +562,11 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
{
int l=buf.length();
if (l>_copy.length)
- l=_copy.length;
- buf.getChars(0,l,_copy,0);
+ l=_copy.length;
+ buf.getChars(0,l,_copy,0);
_writer.write(_copy,0,l);
u8buf.reset();
- _buffers.add(u8buf);
+ _buffers.add(u8buf);
// TODO do outside synchronized scope
if (_extended)
@@ -362,13 +575,13 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
// TODO do outside synchronized scope
if (_logCookies)
{
- Cookie[] cookies = request.getCookies();
+ Cookie[] cookies = request.getCookies();
if (cookies == null || cookies.length == 0)
_writer.write(" -");
else
{
_writer.write(" \"");
- for (int i = 0; i < cookies.length; i++)
+ for (int i = 0; i < cookies.length; i++)
{
if (i != 0)
_writer.write(';');
@@ -379,11 +592,20 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
_writer.write('\"');
}
}
+
+ final long now = System.currentTimeMillis();
+ final long start = request.getTimeStamp();
+ final long dispatch = request.getDispatchTime();
+ if (_logDispatch)
+ {
+ _writer.write(' ');
+ _writer.write(Long.toString(now - (dispatch==0 ? start:dispatch)));
+ }
if (_logLatency)
{
_writer.write(' ');
- _writer.write(TypeUtil.toString(System.currentTimeMillis() - request.getTimeStamp()));
+ _writer.write(Long.toString(now - start));
}
_writer.write(StringUtil.__LINE_SEPARATOR);
@@ -399,9 +621,17 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
}
/* ------------------------------------------------------------ */
- protected void logExtended(Request request,
- Response response,
- Writer writer) throws IOException
+ /**
+ * Writes extended request and response information to the output stream.
+ *
+ * @param request request object
+ * @param response response object
+ * @param writer log file writer
+ * @throws IOException
+ */
+ protected void logExtended(Request request,
+ Response response,
+ Writer writer) throws IOException
{
String referer = request.getHeader(HttpHeaders.REFERER);
if (referer == null)
@@ -425,6 +655,11 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
}
/* ------------------------------------------------------------ */
+ /**
+ * Set up request logging and open log file.
+ *
+ * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
+ */
@Override
protected void doStart() throws Exception
{
@@ -461,6 +696,11 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
}
/* ------------------------------------------------------------ */
+ /**
+ * Close the log file and perform cleanup.
+ *
+ * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
+ */
@Override
protected void doStop() throws Exception
{
@@ -492,28 +732,4 @@ public class NCSARequestLog extends AbstractLifeCycle implements RequestLog
_buffers = null;
_copy = null;
}
-
- /* ------------------------------------------------------------ */
- /**
- * @return the log File Date Format
- */
- public String getFilenameDateFormat()
- {
- return _filenameDateFormat;
- }
-
- /* ------------------------------------------------------------ */
- /**
- * Set the log file date format.
- *
- * @see {@link RolloverFileOutputStream#RolloverFileOutputStream(String, boolean, int, TimeZone, String, String)}
- * @param logFileDateFormat
- * the logFileDateFormat to pass to
- * {@link RolloverFileOutputStream}
- */
- public void setFilenameDateFormat(String logFileDateFormat)
- {
- _filenameDateFormat = logFileDateFormat;
- }
-
}
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 6a06cc8ffa..a1c5599fc6 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
@@ -82,26 +82,26 @@ import org.eclipse.jetty.util.log.Log;
/* ------------------------------------------------------------ */
/** Jetty Request.
* <p>
- * Implements {@link javax.servlet.http.HttpServletRequest} from the {@link javax.servlet.http} package.
+ * Implements {@link javax.servlet.http.HttpServletRequest} from the <code>javax.servlet.http</code> package.
* </p>
* <p>
* The standard interface of mostly getters,
* is extended with setters so that the request is mutable by the handlers that it is
* passed to. This allows the request object to be as lightweight as possible and not
- * actually implement any significant behaviour. For example<ul>
+ * actually implement any significant behavior. For example<ul>
*
- * <li>The {@link Request#getContextPath} method will return null, until the requeset has been
- * passed to a {@link ContextHandler} which matches the {@link Request#getPathInfo} with a context
- * path and calls {@link Request#setContextPath} as a result.</li>
+ * <li>The {@link Request#getContextPath()} method will return null, until the request has been
+ * passed to a {@link ContextHandler} which matches the {@link Request#getPathInfo()} with a context
+ * path and calls {@link Request#setContextPath(String)} as a result.</li>
*
* <li>the HTTP session methods
* will all return null sessions until such time as a request has been passed to
- * a {@link org.eclipse.jetty.servlet.SessionHandler} which checks for session cookies
+ * a {@link org.eclipse.jetty.server.session.SessionHandler} which checks for session cookies
* and enables the ability to create new sessions.</li>
*
- * <li>The {@link Request#getServletPath} method will return null until the request has been
- * passed to a {@link org.eclipse.jetty.servlet.ServletHandler} and the pathInfo matched
- * against the servlet URL patterns and {@link Request#setServletPath} called as a result.</li>
+ * <li>The {@link Request#getServletPath()} method will return null until the request has been
+ * passed to a <code>org.eclipse.jetty.servlet.ServletHandler</code> and the pathInfo matched
+ * against the servlet URL patterns and {@link Request#setServletPath(String)} called as a result.</li>
* </ul>
*
* A request instance is created for each {@link HttpConnection} accepted by the server
@@ -166,7 +166,8 @@ public class Request implements HttpServletRequest
private HttpSession _session;
private SessionManager _sessionManager;
private long _timeStamp;
-
+ private long _dispatchTime;
+
private Buffer _timeStampBuffer;
private HttpURI _uri;
@@ -1225,6 +1226,16 @@ public class Request implements HttpServletRequest
}
/* ------------------------------------------------------------ */
+ /** Get timestamp of the request dispatch
+ *
+ * @return timestamp
+ */
+ public long getDispatchTime()
+ {
+ return _dispatchTime;
+ }
+
+ /* ------------------------------------------------------------ */
public boolean isAsyncStarted()
{
return _async.isAsyncStarted();
@@ -1565,7 +1576,9 @@ public class Request implements HttpServletRequest
/* ------------------------------------------------------------ */
/**
- * @param context
+ * Set request context
+ *
+ * @param context context object
*/
public void setContext(Context context)
{
@@ -1575,7 +1588,8 @@ public class Request implements HttpServletRequest
/* ------------------------------------------------------------ */
/**
- * @return True if this is the first call of takeNewContext() since the last {@link #setContext(Context)} call.
+ * @return True if this is the first call of {@link #takeNewContext()}
+ * since the last {@link #setContext(org.eclipse.jetty.server.handler.ContextHandler.Context)} call.
*/
public boolean takeNewContext()
{
@@ -1587,7 +1601,7 @@ public class Request implements HttpServletRequest
/* ------------------------------------------------------------ */
/**
* Sets the "context path" for this request
- * @see HttpServletRequest#getContextPath
+ * @see HttpServletRequest#getContextPath()
*/
public void setContextPath(String contextPath)
{
@@ -1801,6 +1815,16 @@ public class Request implements HttpServletRequest
}
/* ------------------------------------------------------------ */
+ /** Set timetstamp of request dispatch
+ *
+ * @param value timestamp
+ */
+ public void setDispatchTime(long value)
+ {
+ _dispatchTime = value;
+ }
+
+ /* ------------------------------------------------------------ */
public AsyncContext startAsync() throws IllegalStateException
{
if (!_asyncSupported)
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/RequestLog.java b/jetty-server/src/main/java/org/eclipse/jetty/server/RequestLog.java
index 2e95bbc0e0..a2b7a9b36c 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/RequestLog.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/RequestLog.java
@@ -16,9 +16,8 @@ package org.eclipse.jetty.server;
import org.eclipse.jetty.util.component.LifeCycle;
/**
- * A <code>RequestLog</code> can be attached to a {@link org.eclipse.jetty.server.server.handler.RequestLogHandler} to enable logging of requests/responses.
- *
- * @see Server#setRequestLog
+ * A <code>RequestLog</code> can be attached to a {@link org.eclipse.jetty.server.handler.RequestLogHandler} to enable
+ * logging of requests/responses.
*/
public interface RequestLog extends LifeCycle
{
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 0230f90665..37ed17efca 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
@@ -17,6 +17,8 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Collections;
+import java.util.List;
+import java.util.List;
import java.util.Locale;
import javax.servlet.ServletOutputStream;
@@ -29,6 +31,7 @@ import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeaderValues;
import org.eclipse.jetty.http.HttpHeaders;
+import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersions;
@@ -43,14 +46,10 @@ import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
-/* ------------------------------------------------------------ */
/** Response.
* <p>
- * Implements {@link javax.servlet.HttpServletResponse} from the {@link javax.servlet} package.
+ * Implements {@link javax.servlet.http.HttpServletResponse} from the <code>javax.servlet.http</code> package.
* </p>
- *
- *
- *
*/
public class Response implements HttpServletResponse
{
@@ -156,16 +155,30 @@ public class Response implements HttpServletResponse
*/
public String encodeURL(String url)
{
- Request request=_connection.getRequest();
+ final Request request=_connection.getRequest();
SessionManager sessionManager = request.getSessionManager();
if (sessionManager==null)
return url;
+
+ if (sessionManager.isCheckingRemoteSessionIdEncoding() && URIUtil.hasScheme(url))
+ {
+ HttpURI uri = new HttpURI(url);
+ int port=uri.getPort();
+ if (port<0)
+ port = HttpSchemes.HTTPS.equalsIgnoreCase(uri.getScheme())?443:80;
+ if (!request.getServerName().equalsIgnoreCase(uri.getHost()) ||
+ request.getServerPort()!=port ||
+ !uri.getPath().startsWith(request.getContextPath()))
+ return url;
+ }
+
String sessionURLPrefix = sessionManager.getSessionIdPathParameterNamePrefix();
if (sessionURLPrefix==null)
return url;
if (url==null)
return null;
+
// should not encode if cookies in evidence
if (request.isRequestedSessionIdFromCookie())
{
@@ -190,15 +203,12 @@ public class Response implements HttpServletResponse
if (session == null)
return url;
-
// invalid session
if (!sessionManager.isValid(session))
return url;
String id=sessionManager.getNodeId(session);
-
- // TODO Check host and port are for this server
// Already encoded
int prefix=url.indexOf(sessionURLPrefix);
if (prefix!=-1)
@@ -224,7 +234,7 @@ public class Response implements HttpServletResponse
}
/* ------------------------------------------------------------ */
- /*
+ /**
* @see javax.servlet.http.HttpServletResponse#encodeRedirectURL(java.lang.String)
*/
public String encodeRedirectURL(String url)
@@ -233,21 +243,17 @@ public class Response implements HttpServletResponse
}
/* ------------------------------------------------------------ */
- /*
- * @see javax.servlet.http.HttpServletResponse#encodeUrl(java.lang.String)
- */
+ @Deprecated
public String encodeUrl(String url)
{
return encodeURL(url);
}
/* ------------------------------------------------------------ */
- /*
- * @see javax.servlet.http.HttpServletResponse#encodeRedirectUrl(java.lang.String)
- */
+ @Deprecated
public String encodeRedirectUrl(String url)
{
- return encodeURL(url);
+ return encodeRedirectURL(url);
}
/* ------------------------------------------------------------ */
@@ -288,14 +294,14 @@ public class Response implements HttpServletResponse
ContextHandler.Context context = request.getContext();
if (context!=null)
error_handler=context.getContextHandler().getErrorHandler();
+ if (error_handler==null)
+ error_handler = _connection.getConnector().getServer().getBean(ErrorHandler.class);
if (error_handler!=null)
{
- // TODO - probably should reset these after the request?
request.setAttribute(Dispatcher.ERROR_STATUS_CODE,new Integer(code));
request.setAttribute(Dispatcher.ERROR_MESSAGE, message);
request.setAttribute(Dispatcher.ERROR_REQUEST_URI, request.getRequestURI());
request.setAttribute(Dispatcher.ERROR_SERVLET_NAME,request.getServletName());
-
error_handler.handle(null,_connection.getRequest(),_connection.getRequest(),this );
}
else
@@ -715,7 +721,7 @@ public class Response implements HttpServletResponse
if (_contentType==null)
{
- _contentType = _mimeType+";charset="+QuotedStringTokenizer.quote(_characterEncoding,";= ");
+ _contentType = _mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
}
}
@@ -724,16 +730,16 @@ public class Response implements HttpServletResponse
int i1=_contentType.indexOf("charset=",i0);
if (i1<0)
{
- _contentType = _contentType+";charset="+QuotedStringTokenizer.quote(_characterEncoding,";= ");
+ _contentType = _contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
}
else
{
int i8=i1+8;
int i2=_contentType.indexOf(" ",i8);
if (i2<0)
- _contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quote(_characterEncoding,";= ");
+ _contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
else
- _contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quote(_characterEncoding,";= ")+_contentType.substring(i2);
+ _contentType=_contentType.substring(0,i8)+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ")+_contentType.substring(i2);
}
_connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
}
@@ -861,12 +867,12 @@ public class Response implements HttpServletResponse
}
else if (i2<0)
{
- _contentType=contentType.substring(0,i1)+";charset="+QuotedStringTokenizer.quote(_characterEncoding,";= ");
+ _contentType=contentType.substring(0,i1)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
}
else
{
- _contentType=contentType.substring(0,i1)+contentType.substring(i2)+";charset="+QuotedStringTokenizer.quote(_characterEncoding,";= ");
+ _contentType=contentType.substring(0,i1)+contentType.substring(i2)+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
}
}
@@ -912,7 +918,7 @@ public class Response implements HttpServletResponse
else // No encoding in the params.
{
_cachedMimeType=null;
- _contentType=_characterEncoding==null?contentType:contentType+";charset="+QuotedStringTokenizer.quote(_characterEncoding,";= ");
+ _contentType=_characterEncoding==null?contentType:contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
}
}
@@ -933,13 +939,13 @@ public class Response implements HttpServletResponse
}
else
{
- _contentType=_mimeType+";charset="+QuotedStringTokenizer.quote(_characterEncoding,";= ");
+ _contentType=_mimeType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
}
}
else
{
- _contentType=contentType+";charset="+QuotedStringTokenizer.quote(_characterEncoding,";= ");
+ _contentType=contentType+";charset="+QuotedStringTokenizer.quoteIfNeeded(_characterEncoding,";= ");
_connection.getResponseFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,_contentType);
}
}
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 297e81f538..9ab0a6151d 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
@@ -14,15 +14,12 @@
package org.eclipse.jetty.server;
import java.io.IOException;
-import java.lang.reflect.Method;
+import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
-import java.util.Set;
-import java.util.concurrent.CopyOnWriteArraySet;
-
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -30,7 +27,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpURI;
-import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.Attributes;
@@ -74,7 +70,9 @@ public class Server extends HandlerWrapper implements Attributes
private boolean _sendDateHeader = false; //send Date: header
private int _graceful=0;
private boolean _stopAtShutdown;
+ private int _maxCookieVersion=1;
+
/* ------------------------------------------------------------ */
public Server()
{
@@ -83,7 +81,7 @@ public class Server extends HandlerWrapper implements Attributes
/* ------------------------------------------------------------ */
/** Convenience constructor
- * Creates server and a {@link SocketConnector} at the passed port.
+ * Creates server and a {@link SelectChannelConnector} at the passed port.
*/
public Server(int port)
{
@@ -93,6 +91,20 @@ public class Server extends HandlerWrapper implements Attributes
connector.setPort(port);
setConnectors(new Connector[]{connector});
}
+
+ /* ------------------------------------------------------------ */
+ /** Convenience constructor
+ * Creates server and a {@link SelectChannelConnector} at the passed address.
+ */
+ public Server(InetSocketAddress addr)
+ {
+ setServer(this);
+
+ Connector connector=new SelectChannelConnector();
+ connector.setHost(addr.getHostName());
+ connector.setPort(addr.getPort());
+ setConnectors(new Connector[]{connector});
+ }
/* ------------------------------------------------------------ */
@@ -198,7 +210,13 @@ public class Server extends HandlerWrapper implements Attributes
HttpGenerator.setServerVersion(_version);
MultiException mex=new MultiException();
- Iterator itor = _dependentBeans.iterator();
+ if (_threadPool==null)
+ {
+ QueuedThreadPool tp=new QueuedThreadPool();
+ setThreadPool(tp);
+ }
+
+ Iterator<Object> itor = _dependentBeans.iterator();
while (itor.hasNext())
{
try
@@ -210,12 +228,6 @@ public class Server extends HandlerWrapper implements Attributes
catch (Throwable e) {mex.add(e);}
}
- if (_threadPool==null)
- {
- QueuedThreadPool tp=new QueuedThreadPool();
- setThreadPool(tp);
- }
-
if (_sessionIdManager!=null)
_sessionIdManager.start();
@@ -299,7 +311,7 @@ public class Server extends HandlerWrapper implements Attributes
if (!_dependentBeans.isEmpty())
{
- ListIterator itor = _dependentBeans.listIterator(_dependentBeans.size());
+ ListIterator<Object> itor = _dependentBeans.listIterator(_dependentBeans.size());
while (itor.hasPrevious())
{
try
@@ -313,7 +325,9 @@ public class Server extends HandlerWrapper implements Attributes
}
mex.ifExceptionThrow();
- ShutdownThread.deregister(this);
+
+ if (getStopAtShutdown())
+ ShutdownThread.deregister(this);
}
/* ------------------------------------------------------------ */
@@ -436,13 +450,30 @@ public class Server extends HandlerWrapper implements Attributes
{
return _sendDateHeader;
}
-
+
+ /* ------------------------------------------------------------ */
+ /** Get the maximum cookie version.
+ * @return the maximum set-cookie version sent by this server
+ */
+ public int getMaxCookieVersion()
+ {
+ return _maxCookieVersion;
+ }
+
+ /* ------------------------------------------------------------ */
+ /** Set the maximum cookie version.
+ * @param maxCookieVersion the maximum set-cookie version sent by this server
+ */
+ public void setMaxCookieVersion(int maxCookieVersion)
+ {
+ _maxCookieVersion = maxCookieVersion;
+ }
/* ------------------------------------------------------------ */
/**
* Add a LifeCycle object to be started/stopped
* along with the Server.
- * @deprecated Use {@link #addBean(LifeCycle)}
+ * @deprecated Use {@link #addBean(Object)}
* @param c
*/
@Deprecated
@@ -457,7 +488,7 @@ public class Server extends HandlerWrapper implements Attributes
* The bean will be added to the servers {@link Container}
* and if it is a {@link LifeCycle} instance, it will be
* started/stopped along with the Server.
- * @param c
+ * @param o the bean object to add
*/
public void addBean(Object o)
{
@@ -500,6 +531,34 @@ public class Server extends HandlerWrapper implements Attributes
return beans;
}
+ /* ------------------------------------------------------------ */
+ /** Get dependent bean of a specific class.
+ * If more than one bean of the type exist, the first is returned.
+ * @see #addBean(Object)
+ * @param clazz
+ * @return bean or null
+ */
+ public <T> T getBean(Class<T> clazz)
+ {
+ Iterator<?> iter = _dependentBeans.iterator();
+ T t=null;
+ int count=0;
+ while (iter.hasNext())
+ {
+ Object o = iter.next();
+ if (clazz.isInstance(o))
+ {
+ count++;
+ if (t==null)
+ t=(T)o;
+ }
+ }
+ if (count>1)
+ Log.debug("getBean({}) 1 of {}",clazz.getName(),count);
+
+ return t;
+ }
+
/**
* Remove a LifeCycle object to be started/stopped
* along with the Server
@@ -578,7 +637,7 @@ public class Server extends HandlerWrapper implements Attributes
/* ------------------------------------------------------------ */
/**
- * Set graceful shutdown timeout. If set, the {@link #doStop()} method will not immediately stop the
+ * Set graceful shutdown timeout. If set, the internal <code>doStop()</code> method will not immediately stop the
* server. Instead, all {@link Connector}s will be closed so that new connections will not be accepted
* and all handlers that implement {@link Graceful} will be put into the shutdown mode so that no new requests
* will be accepted, but existing requests can complete. The server will then wait the configured timeout
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionIdManager.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionIdManager.java
index 1d76581822..cca2783673 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/SessionIdManager.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SessionIdManager.java
@@ -20,13 +20,6 @@ import org.eclipse.jetty.util.component.LifeCycle;
/** Session ID Manager.
* Manages session IDs across multiple contexts.
- *
- *
- */
-/* ------------------------------------------------------------ */
-/**
- *
- *
*/
public interface SessionIdManager extends LifeCycle
{
@@ -57,7 +50,7 @@ public interface SessionIdManager extends LifeCycle
/**
* @param request
* @param created
- * @return
+ * @return the new session id
*/
public String newSessionId(HttpServletRequest request,long created);
@@ -68,7 +61,7 @@ public interface SessionIdManager extends LifeCycle
/** Get a cluster ID from a node ID.
* Strip node identifier from a located session ID.
* @param nodeId
- * @return
+ * @return the cluster id
*/
public String getClusterId(String nodeId);
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 3d11dd554a..7d8ea58284 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
@@ -30,14 +30,15 @@ import org.eclipse.jetty.util.component.LifeCycle;
/**
* Session Manager.
* The API required to manage sessions for a servlet context.
+ *
*/
public interface SessionManager extends LifeCycle
{
/* ------------------------------------------------------------ */
/**
* Session cookie name.
- * Defaults to JSESSIONID, but can be set with the
- * org.eclipse.jetty.servlet.SessionCookie context init parameter.
+ * Defaults to <code>JSESSIONID</code>, but can be set with the
+ * <code>org.eclipse.jetty.servlet.SessionCookie</code> context init parameter.
*/
public final static String __SessionCookieProperty = "org.eclipse.jetty.servlet.SessionCookie";
public final static String __DefaultSessionCookie = "JSESSIONID";
@@ -46,12 +47,13 @@ public interface SessionManager extends LifeCycle
/* ------------------------------------------------------------ */
/**
* Session id path parameter name.
- * Defaults to jsessionid, but can be set with the
- * org.eclipse.jetty.servlet.SessionIdPathParameterName context init parameter.
+ * Defaults to <code>jsessionid</code>, but can be set with the
+ * <code>org.eclipse.jetty.servlet.SessionIdPathParameterName</code> context init parameter.
* If set to null or "none" no URL rewriting will be done.
*/
public final static String __SessionIdPathParameterNameProperty = "org.eclipse.jetty.servlet.SessionIdPathParameterName";
public final static String __DefaultSessionIdPathParameterName = "jsessionid";
+ public final static String __CheckRemoteSessionEncoding = "org.eclipse.jetty.servlet.CheckingRemoteSessionIdEncoding";
/* ------------------------------------------------------------ */
@@ -101,6 +103,14 @@ public interface SessionManager extends LifeCycle
*/
public HttpSession newHttpSession(HttpServletRequest request);
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return true if session cookies should be HTTP-only (Microsoft extension)
+ * @see org.eclipse.jetty.http.HttpCookie#isHttpOnly()
+ */
+ public boolean getHttpOnly();
+
/* ------------------------------------------------------------ */
/**
* @return the max period of inactivity, after which the session is invalidated, in seconds.
@@ -267,4 +277,15 @@ public interface SessionManager extends LifeCycle
public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes);
public SessionCookieConfig getSessionCookieConfig();
+
+ /**
+ * @return True if absolute URLs are check for remoteness before being session encoded.
+ */
+ public boolean isCheckingRemoteSessionIdEncoding();
+
+ /**
+ * @param remote True if absolute URLs are check for remoteness before being session encoded.
+ */
+ public void setCheckingRemoteSessionIdEncoding(boolean remote);
+
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java b/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java
index 0c849bd593..8422e85dc3 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/UserIdentity.java
@@ -51,14 +51,11 @@ public interface UserIdentity
/* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
/**
* A UserIdentity Scope.
* A scope is the environment in which a User Identity is to
* be interpreted. Typically it is set by the target servlet of
* a request.
- * @see org.eclipse.jetty.servlet.ServletHolder
*/
interface Scope
{
@@ -83,15 +80,11 @@ public interface UserIdentity
}
/* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
public interface UnauthenticatedUserIdentity extends UserIdentity
{
}
/* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
public static final UserIdentity UNAUTHENTICATED_IDENTITY = new UnauthenticatedUserIdentity()
{
public Subject getSubject()
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/bio/SocketConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/bio/SocketConnector.java
index 5a39e71f38..e3104dbb8d 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/bio/SocketConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/bio/SocketConnector.java
@@ -4,13 +4,13 @@
// 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
+// 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.
+// You may elect to redistribute this code under either of these licenses.
// ========================================================================
-
+
package org.eclipse.jetty.server.bio;
import java.io.IOException;
@@ -39,21 +39,22 @@ import org.eclipse.jetty.util.log.Log;
* This connector implements a traditional blocking IO and threading model.
* Normal JRE sockets are used and a thread is allocated per connection.
* Buffers are managed so that large buffers are only allocated to active connections.
- *
+ *
* This Connector should only be used if NIO is not available.
- *
+ *
* @org.apache.xbean.XBean element="bioConnector" description="Creates a BIO based socket connector"
- *
- *
+ *
+ *
*/
public class SocketConnector extends AbstractConnector
{
protected ServerSocket _serverSocket;
protected final Set<EndPoint> _connections;
-
+ protected volatile int _localPort=-1;
+
/* ------------------------------------------------------------ */
/** Constructor.
- *
+ *
*/
public SocketConnector()
{
@@ -65,7 +66,7 @@ public class SocketConnector extends AbstractConnector
{
return _serverSocket;
}
-
+
/* ------------------------------------------------------------ */
public void open() throws IOException
{
@@ -73,6 +74,10 @@ public class SocketConnector extends AbstractConnector
if (_serverSocket==null || _serverSocket.isClosed())
_serverSocket= newServerSocket(getHost(),getPort(),getAcceptQueueSize());
_serverSocket.setReuseAddress(getReuseAddress());
+ _localPort=_serverSocket.getLocalPort();
+ if (_localPort<=0)
+ throw new IllegalStateException("port not allocated for "+this);
+
}
/* ------------------------------------------------------------ */
@@ -81,26 +86,27 @@ public class SocketConnector extends AbstractConnector
ServerSocket ss= host==null?
new ServerSocket(port,backlog):
new ServerSocket(port,backlog,InetAddress.getByName(host));
-
+
return ss;
}
-
+
/* ------------------------------------------------------------ */
public void close() throws IOException
{
if (_serverSocket!=null)
_serverSocket.close();
_serverSocket=null;
+ _localPort=-2;
}
/* ------------------------------------------------------------ */
@Override
public void accept(int acceptorID)
throws IOException, InterruptedException
- {
+ {
Socket socket = _serverSocket.accept();
configure(socket);
-
+
ConnectorEndPoint connection=new ConnectorEndPoint(socket);
connection.dispatch();
}
@@ -109,7 +115,7 @@ public class SocketConnector extends AbstractConnector
/**
* Allows subclass to override Conection if required.
*/
- protected HttpConnection newHttpConnection(EndPoint endpoint)
+ protected Connection newConnection(EndPoint endpoint)
{
return new HttpConnection(this, endpoint, getServer());
}
@@ -121,21 +127,15 @@ public class SocketConnector extends AbstractConnector
{
ConnectorEndPoint connection = (ConnectorEndPoint)endpoint;
int lrmit = isLowResources()?_lowResourceMaxIdleTime:_maxIdleTime;
- if (connection._sotimeout!=lrmit)
- {
- connection._sotimeout=lrmit;
- ((Socket)endpoint.getTransport()).setSoTimeout(lrmit);
- }
-
+ connection.setMaxIdleTime(lrmit);
+
super.customize(endpoint, request);
}
/* ------------------------------------------------------------------------------- */
public int getLocalPort()
{
- if (_serverSocket==null || _serverSocket.isClosed())
- return -1;
- return _serverSocket.getLocalPort();
+ return _localPort;
}
/* ------------------------------------------------------------------------------- */
@@ -157,7 +157,7 @@ public class SocketConnector extends AbstractConnector
{
set= new HashSet(_connections);
}
-
+
Iterator iter=set.iterator();
while(iter.hasNext())
{
@@ -173,14 +173,12 @@ public class SocketConnector extends AbstractConnector
{
boolean _dispatched=false;
volatile Connection _connection;
- int _sotimeout;
protected final Socket _socket;
-
+
public ConnectorEndPoint(Socket socket) throws IOException
{
- super(socket);
- _connection = newHttpConnection(this);
- _sotimeout=socket.getSoTimeout();
+ super(socket,_maxIdleTime);
+ _connection = newConnection(this);
_socket=socket;
}
@@ -195,7 +193,7 @@ public class SocketConnector extends AbstractConnector
connectionUpgraded(_connection,connection);
_connection=connection;
}
-
+
public void dispatch() throws IOException
{
if (getThreadPool()==null || !getThreadPool().dispatch(this))
@@ -204,7 +202,7 @@ public class SocketConnector extends AbstractConnector
close();
}
}
-
+
@Override
public int fill(Buffer buffer) throws IOException
{
@@ -212,8 +210,8 @@ public class SocketConnector extends AbstractConnector
if (l<0)
close();
return l;
- }
-
+ }
+
@Override
public void close() throws IOException
{
@@ -231,21 +229,14 @@ public class SocketConnector extends AbstractConnector
{
_connections.add(this);
}
-
+
while (isStarted() && !isClosed())
{
if (_connection.isIdle())
{
if (isLowResources())
- {
- int lrmit = getLowResourcesMaxIdleTime();
- if (lrmit>=0 && _sotimeout!= lrmit)
- {
- _sotimeout=lrmit;
- _socket.setSoTimeout(_sotimeout);
- }
- }
- }
+ setMaxIdleTime(getLowResourcesMaxIdleTime());
+ }
_connection=_connection.handle();
}
@@ -269,7 +260,7 @@ public class SocketConnector extends AbstractConnector
catch(IOException e2){Log.ignore(e2);}
}
finally
- {
+ {
connectionClosed(_connection);
synchronized(_connections)
{
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 fbaa3513d2..91a65a19b1 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
@@ -94,6 +94,8 @@ public abstract class AbstractHandlerContainer extends AbstractHandler implement
int last=handlers.length-1;
for (int h=0;h<=last;h++)
{
+ if (handlers[h]==null)
+ continue;
b.append(indent);
b.append(" +-");
if (handlers[h] instanceof AbstractHandler)
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 4938021beb..114a5076b3 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
@@ -4,11 +4,11 @@
// 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
+// 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.
+// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server.handler;
@@ -73,31 +73,35 @@ import org.eclipse.jetty.util.resource.Resource;
/* ------------------------------------------------------------ */
/** ContextHandler.
- *
+ *
* This handler wraps a call to handle by setting the context and
* servlet path, plus setting the context classloader.
- *
+ *
* <p>
* If the context init parameter "org.eclipse.jetty.server.context.ManagedAttributes"
* is set to a comma separated list of names, then they are treated as context
* attribute names, which if set as attributes are passed to the servers Container
* so that they may be managed with JMX.
- *
- * @org.apache.xbean.XBean description="Creates a basic HTTP context"
- *
- *
*
+ * @org.apache.xbean.XBean description="Creates a basic HTTP context"
*/
public class ContextHandler extends ScopedHandler implements Attributes, Server.Graceful
{
private static final ThreadLocal<Context> __context=new ThreadLocal<Context>();
- public static final String MANAGED_ATTRIBUTES = "org.eclipse.jetty.server.context.ManagedAttributes";
+ /**
+ * If a context attribute with this name is set, it is interpreted as a
+ * comma separated list of attribute name. Any other context attributes that
+ * are set with a name from this list will result in a call to {@link #setManagedAttribute(String, Object)},
+ * which typically initiates the creation of a JMX MBean for the attribute value.
+ */
+ public static final String MANAGED_ATTRIBUTES = "org.eclipse.jetty.server.context.ManagedAttributes";
+
/* ------------------------------------------------------------ */
/** Get the current ServletContext implementation.
* This call is only valid during a call to doStart and is available to
* nested handlers to access the context.
- *
+ *
* @return ServletContext implementation
*/
public static Context getCurrentContext()
@@ -106,14 +110,14 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
protected Context _scontext;
-
- private AttributesMap _attributes;
- private AttributesMap _contextAttributes;
+
+ private final AttributesMap _attributes;
+ private final AttributesMap _contextAttributes;
+ private final Map<String,String> _initParams;
private ClassLoader _classLoader;
private String _contextPath="/";
- private Map<String,String> _initParams;
private String _displayName;
- private Resource _baseResource;
+ private Resource _baseResource;
private MimeTypes _mimeTypes;
private Map<String,String> _localeEncodingMap;
private String[] _welcomeFiles;
@@ -134,49 +138,51 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
private Map<String,Object> _managedAttributes;
private boolean _shutdown=false;
- private boolean _available=true;
+ private boolean _available=true;
private volatile int _availability; // 0=STOPPED, 1=AVAILABLE, 2=SHUTDOWN, 3=UNAVAILABLE
-
+
private final static int __STOPPED=0,__AVAILABLE=1,__SHUTDOWN=2,__UNAVAILABLE=3;
-
-
+
+
/* ------------------------------------------------------------ */
/**
- *
+ *
*/
public ContextHandler()
{
super();
_scontext=new Context();
_attributes=new AttributesMap();
+ _contextAttributes=new AttributesMap();
_initParams=new HashMap<String,String>();
}
-
+
/* ------------------------------------------------------------ */
/**
- *
+ *
*/
protected ContextHandler(Context context)
{
super();
_scontext=context;
_attributes=new AttributesMap();
+ _contextAttributes=new AttributesMap();
_initParams=new HashMap<String,String>();
}
-
+
/* ------------------------------------------------------------ */
/**
- *
+ *
*/
public ContextHandler(String contextPath)
{
this();
setContextPath(contextPath);
}
-
+
/* ------------------------------------------------------------ */
/**
- *
+ *
*/
public ContextHandler(HandlerContainer parent, String contextPath)
{
@@ -193,7 +199,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
return _scontext;
}
-
+
/* ------------------------------------------------------------ */
/**
* @return the allowNullPathInfo true if /context is not redirected to /context/
@@ -221,13 +227,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
Server old_server=getServer();
if (old_server!=null && old_server!=server)
old_server.getContainer().update(this, _errorHandler, null, "error",true);
- super.setServer(server);
+ super.setServer(server);
if (server!=null && server!=old_server)
server.getContainer().update(this, null, _errorHandler, "error",true);
- _errorHandler.setServer(server);
+ _errorHandler.setServer(server);
}
else
- super.setServer(server);
+ super.setServer(server);
}
/* ------------------------------------------------------------ */
@@ -247,8 +253,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
if ( vhosts == null )
{
_vhosts = vhosts;
- }
- else
+ }
+ else
{
_vhosts = new String[vhosts.length];
for ( int i = 0; i < vhosts.length; i++ )
@@ -274,8 +280,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /**
- * @deprecated use {@link #setConnectorNames(String[])}
+ /**
+ * @deprecated use {@link #setConnectorNames(String[])}
*/
@Deprecated
public void setHosts(String[] hosts)
@@ -302,15 +308,15 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
if (_connectors==null || _connectors.size()==0)
return null;
-
+
return _connectors.toArray(new String[_connectors.size()]);
}
/* ------------------------------------------------------------ */
/** Set the names of accepted connectors.
- *
+ *
* Names are either "host:port" or a specific configured name for a connector.
- *
+ *
* @param connectors If non null, an array of connector names that this context
* will accept a request from.
*/
@@ -321,9 +327,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
else
_connectors= new HashSet<String>(Arrays.asList(connectors));
}
-
+
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getAttribute(java.lang.String)
*/
public Object getAttribute(String name)
@@ -332,7 +338,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getAttributeNames()
*/
@SuppressWarnings("unchecked")
@@ -340,7 +346,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
return AttributesMap.getAttributeNamesCopy(_attributes);
}
-
+
/* ------------------------------------------------------------ */
/**
* @return Returns the attributes.
@@ -349,7 +355,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
return _attributes;
}
-
+
/* ------------------------------------------------------------ */
/**
* @return Returns the classLoader.
@@ -402,9 +408,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
return _contextPath;
}
-
+
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getInitParameter(java.lang.String)
*/
public String getInitParameter(String name)
@@ -413,7 +419,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getInitParameterNames()
*/
@SuppressWarnings("unchecked")
@@ -421,7 +427,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
return Collections.enumeration(_initParams.keySet());
}
-
+
/* ------------------------------------------------------------ */
/**
* @return Returns the initParams.
@@ -432,7 +438,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getServletContextName()
*/
public String getDisplayName()
@@ -445,7 +451,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
return _eventListeners;
}
-
+
/* ------------------------------------------------------------ */
/**
* Set the context event listeners.
@@ -460,26 +466,26 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
_contextAttributeListeners=null;
_requestListeners=null;
_requestAttributeListeners=null;
-
+
_eventListeners=eventListeners;
-
+
for (int i=0; eventListeners!=null && i<eventListeners.length;i ++)
{
EventListener listener = _eventListeners[i];
-
+
if (listener instanceof ServletContextListener)
_contextListeners= LazyList.add(_contextListeners, listener);
-
+
if (listener instanceof ServletContextAttributeListener)
_contextAttributeListeners= LazyList.add(_contextAttributeListeners, listener);
-
+
if (listener instanceof ServletRequestListener)
_requestListeners= LazyList.add(_requestListeners, listener);
-
+
if (listener instanceof ServletRequestAttributeListener)
_requestAttributeListeners= LazyList.add(_requestAttributeListeners, listener);
}
- }
+ }
/* ------------------------------------------------------------ */
/**
@@ -489,7 +495,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
* @see ServletRequestListener
* @see ServletRequestAttributeListener
*/
- public void addEventListener(EventListener listener)
+ public void addEventListener(EventListener listener)
{
setEventListeners((EventListener[])LazyList.addToArray(getEventListeners(), listener, EventListener.class));
}
@@ -557,34 +563,34 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
return _logger;
}
-
+
/* ------------------------------------------------------------ */
public void setLogger(Logger logger)
{
_logger=logger;
}
-
+
/* ------------------------------------------------------------ */
- /*
+ /*
* @see org.eclipse.thread.AbstractLifeCycle#doStart()
*/
@Override
protected void doStart() throws Exception
{
_availability=__STOPPED;
-
+
if (_contextPath==null)
throw new IllegalStateException("Null contextPath");
-
+
_logger=Log.getLogger(getDisplayName()==null?getContextPath():getDisplayName());
ClassLoader old_classloader=null;
Thread current_thread=null;
Context old_context=null;
- _contextAttributes=new AttributesMap();
+ _contextAttributes.clearAttributes();
try
{
-
+
// Set the classloader
if (_classLoader!=null)
{
@@ -592,46 +598,40 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
old_classloader=current_thread.getContextClassLoader();
current_thread.setContextClassLoader(_classLoader);
}
-
+
if (_mimeTypes==null)
_mimeTypes=new MimeTypes();
-
+
old_context=__context.get();
__context.set(_scontext);
-
- if (_errorHandler==null)
- setErrorHandler(new ErrorHandler());
-
-
+
// defers the calling of super.doStart()
startContext();
-
_availability=_shutdown?__SHUTDOWN:_available?__AVAILABLE:__UNAVAILABLE;
}
finally
{
__context.set(old_context);
-
+
// reset the classloader
if (_classLoader!=null)
{
current_thread.setContextClassLoader(old_classloader);
}
-
+
}
}
/* ------------------------------------------------------------ */
/**
* Extensible startContext.
- * this method is called from {@link ContextHandler#doStart()} instead of a
+ * this method is called from {@link ContextHandler#doStart()} instead of a
* call to super.doStart(). This allows derived classes to insert additional
* handling (Eg configuration) before the call to super.doStart by this method
* will start contained handlers.
- * @see org.eclipse.jetty.Scope.Context
- * @see org.eclipse.jetty.webapp.WebAppContext
+ * @see org.eclipse.jetty.server.handler.ContextHandler.Context
*/
protected void startContext()
throws Exception
@@ -643,21 +643,21 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
String[] attributes = managedAttributes.split(",");
for (String attribute : attributes)
_managedAttributes.put(attribute,null);
-
+
Enumeration e = _scontext.getAttributeNames();
while(e.hasMoreElements())
{
String name = (String)e.nextElement();
Object value = _scontext.getAttribute(name);
- setManagedAttribute(name,value);
+ checkManagedAttribute(name,value);
}
- }
-
+ }
+
super.doStart();
if (_errorHandler!=null)
_errorHandler.start();
-
+
// Context listeners
if (_contextListeners != null )
{
@@ -668,14 +668,14 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
}
}
-
+
public void callContextInitialized (ServletContextListener l, ServletContextEvent e)
{
l.contextInitialized(e);
}
-
+
public void callContextDestroyed (ServletContextListener l, ServletContextEvent e)
{
l.contextDestroyed(e);
@@ -684,14 +684,14 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/* ------------------------------------------------------------ */
- /*
+ /*
* @see org.eclipse.thread.AbstractLifeCycle#doStop()
*/
@Override
protected void doStop() throws Exception
{
_availability=__STOPPED;
-
+
ClassLoader old_classloader=null;
Thread current_thread=null;
@@ -706,9 +706,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
old_classloader=current_thread.getContextClassLoader();
current_thread.setContextClassLoader(_classLoader);
}
-
+
super.doStop();
-
+
// Context listeners
if (_contextListeners != null )
{
@@ -721,12 +721,12 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
if (_errorHandler!=null)
_errorHandler.stop();
-
+
Enumeration e = _scontext.getAttributeNames();
while(e.hasMoreElements())
{
String name = (String)e.nextElement();
- setManagedAttribute(name,null);
+ checkManagedAttribute(name,null);
}
}
finally
@@ -737,20 +737,18 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
current_thread.setContextClassLoader(old_classloader);
}
- if (_contextAttributes!=null)
- _contextAttributes.clearAttributes();
- _contextAttributes=null;
+ _contextAttributes.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, ServletException
- {
+ {
DispatcherType dispatch=baseRequest.getDispatcherType();
-
+
switch(_availability)
{
case __STOPPED:
@@ -763,14 +761,14 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
if((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
return false;
}
-
+
// Check the vhosts
if (_vhosts!=null && _vhosts.length>0)
{
String vhost = normalizeHostname( baseRequest.getServerName());
boolean match=false;
-
+
// TODO non-linear lookup
for (int i=0;!match && i<_vhosts.length;i++)
{
@@ -785,7 +783,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
if (!match)
return false;
}
-
+
// Check the connector
if (_connectors!=null && _connectors.size()>0)
{
@@ -794,29 +792,31 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
return false;
}
-
- if (target.startsWith(_contextPath))
+ // Are we not the root context?
+ if (_contextPath.length()>1)
{
- if (_contextPath.length()==target.length() && _contextPath.length()>1 &&!_allowNullPathInfo)
+ // reject requests that are not for us
+ if (!target.startsWith(_contextPath))
+ return false;
+ if (target.length()>_contextPath.length() && target.charAt(_contextPath.length())!='/')
+ return false;
+
+ // redirect null path infos
+ if (!_allowNullPathInfo && _contextPath.length()==target.length())
{
// context request must end with /
baseRequest.setHandled(true);
if (baseRequest.getQueryString()!=null)
response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH)+"?"+baseRequest.getQueryString());
- else
+ else
response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
return false;
}
}
- else
- {
- // Not for this context!
- return false;
- }
-
+
return true;
- }
-
+ }
+
/* ------------------------------------------------------------ */
@@ -825,7 +825,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
*/
@Override
public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
+ {
Context old_context=null;
String old_context_path=null;
String old_servlet_path=null;
@@ -835,9 +835,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
String pathInfo=null;
DispatcherType dispatch=baseRequest.getDispatcherType();
-
+
old_context=baseRequest.getContext();
-
+
// Are we already in this context?
if (old_context!=_scontext)
{
@@ -848,7 +848,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
target=URIUtil.compactPath(target);
if (!checkContext(target,baseRequest,response))
return;
-
+
if (target.length()>_contextPath.length())
{
if (_contextPath.length()>1)
@@ -875,13 +875,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
current_thread.setContextClassLoader(_classLoader);
}
}
-
+
try
{
old_context_path=baseRequest.getContextPath();
old_servlet_path=baseRequest.getServletPath();
old_path_info=baseRequest.getPathInfo();
-
+
// Update the paths
baseRequest.setContext(_scontext);
if (!DispatcherType.INCLUDE.equals(dispatch) && target.startsWith("/"))
@@ -893,16 +893,15 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
baseRequest.setServletPath(null);
baseRequest.setPathInfo(pathInfo);
}
-
+
// start manual inline of nextScope(target,baseRequest,request,response);
- //noinspection ConstantIfStatement
- if (false)
+ if (never())
nextScope(target,baseRequest,request,response);
else if (_nextScope!=null)
_nextScope.doScope(target,baseRequest,request, response);
else if (_outerScope!=null)
_outerScope.doHandle(target,baseRequest,request, response);
- else
+ else
doHandle(target,baseRequest,request, response);
// end manual inline (pathentic attempt to reduce stack depth)
}
@@ -915,16 +914,16 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
current_thread.setContextClassLoader(old_classloader);
}
-
+
// reset the context and servlet path.
baseRequest.setContext(old_context);
baseRequest.setContextPath(old_context_path);
baseRequest.setServletPath(old_servlet_path);
- baseRequest.setPathInfo(old_path_info);
+ baseRequest.setPathInfo(old_path_info);
}
}
}
-
+
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.handler.ScopedHandler#doHandle(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
@@ -954,13 +953,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
((ServletRequestListener)LazyList.get(_requestListeners,i)).requestInitialized(sre);
}
}
-
+
if (DispatcherType.REQUEST.equals(dispatch) && isProtectedTarget(target))
throw new HttpException(HttpServletResponse.SC_NOT_FOUND);
-
+
// start manual inline of nextHandle(target,baseRequest,request,response);
//noinspection ConstantIfStatement
- if (false)
+ if (never())
nextHandle(target,baseRequest,request,response);
else if (_nextScope!=null && _nextScope==_handler)
_nextScope.doHandle(target,baseRequest,request, response);
@@ -985,7 +984,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
for(int i=0;i<s;i++)
((ServletRequestListener)LazyList.get(_requestListeners,i)).requestDestroyed(sre);
}
-
+
if (_requestAttributeListeners!=null)
{
for(int i=LazyList.size(_requestAttributeListeners);i-->0;)
@@ -994,12 +993,12 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
}
}
-
+
/* ------------------------------------------------------------ */
/* Handle a runnable in this context
*/
public void handle(Runnable runnable)
- {
+ {
ClassLoader old_classloader=null;
Thread current_thread=null;
try
@@ -1011,7 +1010,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
old_classloader=current_thread.getContextClassLoader();
current_thread.setContextClassLoader(_classLoader);
}
-
+
runnable.run();
}
finally
@@ -1028,64 +1027,49 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
* Called by {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)} when a
* target within a context is determined. If the target is protected, 404 is returned.
* The default implementation always returns false.
- * @see org.eclipse.jetty.webapp.WebAppContext#isProtectedTarget(String)
*/
/* ------------------------------------------------------------ */
protected boolean isProtectedTarget(String target)
- {
+ {
return false;
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
*/
public void removeAttribute(String name)
{
- setManagedAttribute(name,null);
+ checkManagedAttribute(name,null);
_attributes.removeAttribute(name);
}
/* ------------------------------------------------------------ */
/* Set a context attribute.
* Attributes set via this API cannot be overriden by the ServletContext.setAttribute API.
- * Their lifecycle spans the stop/start of a context. No attribute listener events are
+ * Their lifecycle spans the stop/start of a context. No attribute listener events are
* triggered by this API.
* @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object)
*/
public void setAttribute(String name, Object value)
{
- setManagedAttribute(name,value);
+ checkManagedAttribute(name,value);
_attributes.setAttribute(name,value);
}
-
+
/* ------------------------------------------------------------ */
/**
* @param attributes The attributes to set.
*/
public void setAttributes(Attributes attributes)
{
- if (attributes instanceof AttributesMap)
- {
- _attributes = (AttributesMap)attributes;
- Enumeration e = _attributes.getAttributeNames();
- while (e.hasMoreElements())
- {
- String name = (String)e.nextElement();
- setManagedAttribute(name,attributes.getAttribute(name));
- }
- }
- else
+ _attributes.clearAttributes();
+ _attributes.addAll(attributes);
+ Enumeration e = _attributes.getAttributeNames();
+ while (e.hasMoreElements())
{
- _attributes=new AttributesMap();
- Enumeration e = attributes.getAttributeNames();
- while (e.hasMoreElements())
- {
- String name = (String)e.nextElement();
- Object value=attributes.getAttribute(name);
- setManagedAttribute(name,value);
- _attributes.setAttribute(name,value);
- }
+ String name = (String)e.nextElement();
+ checkManagedAttribute(name,attributes.getAttribute(name));
}
}
@@ -1096,28 +1080,28 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
while (e.hasMoreElements())
{
String name = (String)e.nextElement();
- setManagedAttribute(name,null);
+ checkManagedAttribute(name,null);
}
_attributes.clearAttributes();
}
/* ------------------------------------------------------------ */
- private void setManagedAttribute(String name, Object value)
- {
+ public void checkManagedAttribute(String name, Object value)
+ {
if (_managedAttributes!=null && _managedAttributes.containsKey(name))
{
- Object old =_managedAttributes.put(name,value);
- if (old!=null)
- getServer().getContainer().removeBean(old);
- if (value!=null)
- {
- if (_logger.isDebugEnabled()) _logger.debug("Managing "+name);
- getServer().getContainer().addBean(value);
- }
+ setManagedAttribute(name,value);
}
}
/* ------------------------------------------------------------ */
+ public void setManagedAttribute(String name, Object value)
+ {
+ Object old =_managedAttributes.put(name,value);
+ getServer().getContainer().update(this,old,value,name);
+ }
+
+ /* ------------------------------------------------------------ */
/**
* @param classLoader The classLoader to set.
*/
@@ -1125,7 +1109,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
_classLoader = classLoader;
}
-
+
/* ------------------------------------------------------------ */
/**
* @param contextPath The _contextPath to set.
@@ -1135,7 +1119,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
if (contextPath!=null && contextPath.length()>1 && contextPath.endsWith("/"))
throw new IllegalArgumentException("ends with /");
_contextPath = contextPath;
-
+
if (getServer()!=null && (getServer().isStarting() || getServer().isStarted()))
{
Handler[] contextCollections = getServer().getChildHandlersByClass(ContextHandlerCollection.class);
@@ -1143,18 +1127,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
((ContextHandlerCollection)contextCollections[h]).mapContexts();
}
}
-
- /* ------------------------------------------------------------ */
- /**
- * @param initParams The initParams to set.
- */
- public void setInitParams(Map<String,String> initParams)
- {
- if (initParams == null)
- return;
- _initParams = new HashMap<String,String>(initParams);
- }
-
+
/* ------------------------------------------------------------ */
/**
* @param servletContextName The servletContextName to set.
@@ -1163,7 +1136,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
_displayName = servletContextName;
}
-
+
/* ------------------------------------------------------------ */
/**
* @return Returns the resourceBase.
@@ -1185,12 +1158,12 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
return null;
return _baseResource.toString();
}
-
+
/* ------------------------------------------------------------ */
/**
* @param base The resourceBase to set.
*/
- public void setBaseResource(Resource base)
+ public void setBaseResource(Resource base)
{
_baseResource=base;
}
@@ -1199,7 +1172,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/**
* @param resourceBase The base resource as a string.
*/
- public void setResourceBase(String resourceBase)
+ public void setResourceBase(String resourceBase)
{
try
{
@@ -1238,7 +1211,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
return _mimeTypes;
}
-
+
/* ------------------------------------------------------------ */
/**
* @param mimeTypes The mimeTypes to set.
@@ -1251,7 +1224,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/* ------------------------------------------------------------ */
/**
*/
- public void setWelcomeFiles(String[] files)
+ public void setWelcomeFiles(String[] files)
{
_welcomeFiles=files;
}
@@ -1262,7 +1235,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
* @see <a href="http://jcp.org/aboutJava/communityprocess/final/jsr154/index.html">The Servlet Specification</a>
* @see #setWelcomeFiles
*/
- public String[] getWelcomeFiles()
+ public String[] getWelcomeFiles()
{
return _welcomeFiles;
}
@@ -1288,13 +1261,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
getServer().getContainer().update(this, _errorHandler, errorHandler, "errorHandler",true);
_errorHandler = errorHandler;
}
-
+
/* ------------------------------------------------------------ */
public int getMaxFormContentSize()
{
return _maxFormContentSize;
}
-
+
/* ------------------------------------------------------------ */
public void setMaxFormContentSize(int maxSize)
{
@@ -1324,7 +1297,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
@Override
public String toString()
{
-
+
return super.toString()+"@"+Integer.toHexString(hashCode())+getContextPath()+","+getBaseResource();
}
@@ -1334,13 +1307,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
if (className==null)
return null;
-
+
if (_classLoader==null)
return Loader.loadClass(this.getClass(), className);
return _classLoader.loadClass(className);
}
-
+
/* ------------------------------------------------------------ */
public void addLocaleEncoding(String locale,String encoding)
@@ -1349,12 +1322,12 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
_localeEncodingMap=new HashMap<String,String>();
_localeEncodingMap.put(locale, encoding);
}
-
+
/* ------------------------------------------------------------ */
/**
* Get the character encoding for a locale. The full locale name is first
* looked up in the map of encodings. If no encoding is found, then the
- * locale language is looked up.
+ * locale language is looked up.
*
* @param locale a <code>Locale</code> value
* @return a <code>String</code> representing the character encoding for
@@ -1369,7 +1342,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
encoding = _localeEncodingMap.get(locale.getLanguage());
return encoding;
}
-
+
public String getLocaleEncoding (String locale)
{
if (_localeEncodingMap==null)
@@ -1379,13 +1352,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
*/
public Resource getResource(String path) throws MalformedURLException
{
if (path==null || !path.startsWith(URIUtil.SLASH))
throw new MalformedURLException(path);
-
+
if (_baseResource==null)
return null;
@@ -1393,7 +1366,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
path=URIUtil.canonicalPath(path);
Resource resource=_baseResource.addPath(path);
-
+
if (!_aliases && resource.getAlias()!=null)
{
if (resource.exists())
@@ -1402,20 +1375,20 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
Log.debug("Aliased resource: "+resource+"~="+resource.getAlias());
return null;
}
-
+
return resource;
}
catch(Exception e)
{
Log.ignore(e);
}
-
+
return null;
}
/* ------------------------------------------------------------ */
/** Convert URL to Resource
- * wrapper for {@link Resource#newResource(URL)} enables extensions to
+ * wrapper for {@link Resource#newResource(URL)} enables extensions to
* provide alternate resource implementations.
*/
public Resource newResource(URL url) throws IOException
@@ -1425,7 +1398,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/* ------------------------------------------------------------ */
/** Convert URL to Resource
- * wrapper for {@link Resource#newResource(String)} enables extensions to
+ * wrapper for {@link Resource#newResource(String)} enables extensions to
* provide alternate resource implementations.
*/
public Resource newResource(String url) throws IOException
@@ -1434,20 +1407,20 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
*/
public Set<String> getResourcePaths(String path)
- {
+ {
try
{
path=URIUtil.canonicalPath(path);
Resource resource=getResource(path);
-
+
if (resource!=null && resource.exists())
{
if (!path.endsWith(URIUtil.SLASH))
path=path+URIUtil.SLASH;
-
+
String[] l=resource.list();
if (l!=null)
{
@@ -1455,7 +1428,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
for(int i=0;i<l.length;i++)
set.add(path+l[i]);
return set;
- }
+ }
}
}
catch(Exception e)
@@ -1472,20 +1445,20 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
if ( host == null )
return null;
-
+
if ( host.endsWith( "." ) )
return host.substring( 0, host.length() -1);
-
+
return host;
}
-
+
/* ------------------------------------------------------------ */
/** Context.
* <p>
* A partial implementation of {@link javax.servlet.ServletContext}.
- * A complete implementation is provided by the derived {@link org.eclipse.jetty.servlet.ServletContextHandler.Context}.
+ * A complete implementation is provided by the derived {@link ContextHandler}.
* </p>
- *
+ *
*
*/
public class Context implements ServletContext
@@ -1507,14 +1480,12 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getContext(java.lang.String)
*/
@Override
public ServletContext getContext(String uripath)
{
- // TODO this is a very poor implementation!
- // TODO move this to Server
ContextHandler context=null;
Handler[] handlers = getServer().getChildHandlersByClass(ContextHandler.class);
for (int i=0;i<handlers.length;i++)
@@ -1523,20 +1494,21 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
continue;
ContextHandler ch = (ContextHandler)handlers[i];
String context_path=ch.getContextPath();
- if (uripath.equals(context_path) || (uripath.startsWith(context_path)&&uripath.charAt(context_path.length())=='/'))
+
+ if (uripath.equals(context_path) || (uripath.startsWith(context_path)&&uripath.charAt(context_path.length())=='/') || "/".equals(context_path))
{
if (context==null || context_path.length()>context.getContextPath().length())
context=ch;
}
}
-
+
if (context!=null)
return context._scontext;
return null;
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getMajorVersion()
*/
@Override
@@ -1547,7 +1519,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getMimeType(java.lang.String)
*/
@Override
@@ -1562,7 +1534,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getMinorVersion()
*/
@Override
@@ -1572,7 +1544,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String)
*/
@Override
@@ -1582,7 +1554,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getRequestDispatcher(java.lang.String)
*/
@Override
@@ -1593,7 +1565,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
if (!uriInContext.startsWith("/"))
return null;
-
+
try
{
String query=null;
@@ -1619,7 +1591,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getRealPath(java.lang.String)
*/
@Override
@@ -1631,7 +1603,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
path = URIUtil.SLASH;
else if(path.charAt(0)!='/')
path = URIUtil.SLASH + path;
-
+
try
{
Resource resource=ContextHandler.this.getResource(path);
@@ -1646,7 +1618,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
Log.ignore(e);
}
-
+
return null;
}
@@ -1659,9 +1631,9 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
return resource.getURL();
return null;
}
-
+
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getResourceAsStream(java.lang.String)
*/
@Override
@@ -1682,17 +1654,17 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getResourcePaths(java.lang.String)
*/
@Override
public Set getResourcePaths(String path)
- {
+ {
return ContextHandler.this.getResourcePaths(path);
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getServerInfo()
*/
@Override
@@ -1702,7 +1674,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getServlet(java.lang.String)
*/
@Override
@@ -1713,7 +1685,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getServletNames()
*/
@SuppressWarnings("unchecked")
@@ -1725,7 +1697,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getServlets()
*/
@SuppressWarnings("unchecked")
@@ -1737,7 +1709,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#log(java.lang.Exception, java.lang.String)
*/
@Override
@@ -1747,7 +1719,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#log(java.lang.String)
*/
@Override
@@ -1757,7 +1729,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#log(java.lang.String, java.lang.Throwable)
*/
@Override
@@ -1767,7 +1739,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getInitParameter(java.lang.String)
*/
@Override
@@ -1777,7 +1749,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getInitParameterNames()
*/
@SuppressWarnings("unchecked")
@@ -1788,7 +1760,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getAttribute(java.lang.String)
*/
@Override
@@ -1801,7 +1773,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getAttributeNames()
*/
@SuppressWarnings("unchecked")
@@ -1818,33 +1790,25 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
Enumeration<String> e = _attributes.getAttributeNames();
while(e.hasMoreElements())
set.add(e.nextElement());
-
+
return Collections.enumeration(set);
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object)
*/
@Override
public synchronized void setAttribute(String name, Object value)
{
-
- if (_contextAttributes==null)
- {
- // Set it on the handler
- ContextHandler.this.setAttribute(name, value);
- return;
- }
-
- setManagedAttribute(name,value);
+ checkManagedAttribute(name,value);
Object old_value=_contextAttributes.getAttribute(name);
-
+
if (value==null)
_contextAttributes.removeAttribute(name);
else
_contextAttributes.setAttribute(name,value);
-
+
if (_contextAttributeListeners!=null)
{
ServletContextAttributeEvent event =
@@ -1853,7 +1817,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
for(int i=0;i<LazyList.size(_contextAttributeListeners);i++)
{
ServletContextAttributeListener l = (ServletContextAttributeListener)LazyList.get(_contextAttributeListeners,i);
-
+
if (old_value==null)
l.attributeAdded(event);
else if (value==null)
@@ -1865,21 +1829,21 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
*/
@Override
public synchronized void removeAttribute(String name)
{
- setManagedAttribute(name,null);
-
+ checkManagedAttribute(name,null);
+
if (_contextAttributes==null)
{
// Set it on the handler
_attributes.removeAttribute(name);
return;
}
-
+
Object old_value=_contextAttributes.getAttribute(name);
_contextAttributes.removeAttribute(name);
if (old_value!=null)
@@ -1896,7 +1860,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see javax.servlet.ServletContext#getServletContextName()
*/
@Override
@@ -1914,7 +1878,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
{
if ((_contextPath != null) && _contextPath.equals(URIUtil.SLASH))
return "";
-
+
return _contextPath;
}
@@ -2128,7 +2092,6 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
return _minorVersion;
}
-
public void setEffectiveMajorVersion (int v)
{
_majorVersion = v;
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 c91e067ed3..4972bcf586 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
@@ -33,7 +33,7 @@ import org.eclipse.jetty.util.log.Log;
/** ContextHandlerCollection.
*
* This {@link org.eclipse.jetty.server.handler.HandlerCollection} is creates a
- * {@link org.eclipse.jetty.http.servlet.PathMap} to it's contained handlers based
+ * {@link org.eclipse.jetty.http.PathMap} to it's contained handlers based
* on the context path and virtual hosts of any contained {@link org.eclipse.jetty.server.handler.ContextHandler}s.
* The contexts do not need to be directly contained, only children of the contained handlers.
* Multiple contexts may have the same context path and they are called in order until one
@@ -265,9 +265,7 @@ public class ContextHandlerCollection extends HandlerCollection
/* ------------------------------------------------------------ */
/** Add a context handler.
* @param contextPath The context path to add
- * @return
- * @throws IllegalAccessException
- * @throws InstantiationException
+ * @return the ContextHandler just added
*/
public ContextHandler addContext(String contextPath,String resourceBase)
{
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 232aba637c..073c0dfde9 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
@@ -50,6 +50,7 @@ public class DefaultHandler extends AbstractHandler
final long _faviconModified=(System.currentTimeMillis()/1000)*1000;
byte[] _favicon;
boolean _serveIcon=true;
+ boolean _showContexts=true;
public DefaultHandler()
{
@@ -114,44 +115,47 @@ public class DefaultHandler extends AbstractHandler
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);
-
- for (int i=0;handlers!=null && i<handlers.length;i++)
+
+ if (_showContexts)
{
- 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("Contexts known to this server are: <ul>");
+
+ Server server = getServer();
+ Handler[] handlers = server==null?null:server.getChildHandlersByClass(ContextHandler.class);
+
+ 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");
+ }
}
}
@@ -183,6 +187,15 @@ public class DefaultHandler extends AbstractHandler
{
_serveIcon = serveIcon;
}
+
+ public boolean getShowContexts()
+ {
+ return _showContexts;
+ }
+ public void setShowContexts(boolean show)
+ {
+ _showContexts = show;
+ }
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java
index a8dabdaf56..6a422e9be8 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ErrorHandler.java
@@ -27,13 +27,11 @@ import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.ByteArrayISO8859Writer;
-
/* ------------------------------------------------------------ */
/** Handler for Error pages
- * A handler that is registered at the org.eclipse.http.ErrorHandler
- * context attributed and called by the HttpResponse.sendError method to write a
- * error page.
- *
+ * An ErrorHandler is registered with {@link ContextHandler#setErrorHandler(ErrorHandler)} or
+ * {@link org.eclipse.jetty.server.Server#addBean(Object)}.
+ * It is called by the HttpResponse.sendError method to write a error page.
*
*/
public class ErrorHandler extends AbstractHandler
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 7746bf5d75..fdb840030e 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
@@ -109,8 +109,8 @@ public class HandlerCollection extends AbstractHandlerContainer
}
/* ------------------------------------------------------------ */
- /*
- * @see org.eclipse.jetty.server.server.EventHandler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ /**
+ * @see Handler#handle(String, Request, HttpServletRequest, HttpServletResponse)
*/
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerList.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerList.java
index c25ab0e18e..35b067f508 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerList.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerList.java
@@ -24,15 +24,15 @@ import org.eclipse.jetty.server.Request;
/* ------------------------------------------------------------ */
/** HandlerList.
- * This extension of {@link org.eclipse.jetty.server.server.handler.HandlerCollection} will call
+ * This extension of {@link HandlerCollection} will call
* each contained handler in turn until either an exception is thrown, the response
* is committed or a positive response status is set.
*/
public class HandlerList extends HandlerCollection
{
/* ------------------------------------------------------------ */
- /*
- * @see org.eclipse.jetty.server.server.EventHandler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+ /**
+ * @see Handler#handle(String, Request, HttpServletRequest, HttpServletResponse)
*/
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java
index 6ed3d15fdd..ebcaadf9d0 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/IPAccessHandler.java
@@ -14,10 +14,9 @@
package org.eclipse.jetty.server.handler;
import java.io.IOException;
-import java.util.HashMap;
+import java.util.Collections;
import java.util.List;
import java.util.Map;
-import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@@ -28,78 +27,150 @@ import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.util.IPAddressMap;
+import org.eclipse.jetty.util.log.Log;
/**
* IP Access Handler
* <p>
- * Control access to the wrapped handler by the real remote IP.
- * The real IP of the connection is used (not the IP reported in the forwarded for headers),
- * as this cannot be as easily forged.
+ * Controls access to the wrapped handler by the real remote IP. Control is provided
+ * by white/black lists that include both internet addresses and URIs. This handler
+ * uses the real internet address of the connection, not one reported in the forwarded
+ * for headers, as this cannot be as easily forged.
* <p>
- * Control is provided by white/black lists of both internet addresses and URIs.
- * Internet addresses may be absolute (eg 10.1.2.3) or a prefix pattern (eg 10.1.3. ).
- * URI patterns follow the servlet specification for simple prefix and suffix wild cards.
+ * Typically, the black/white lists will be used in one of three modes:
+ * <ul>
+ * <li>Blocking a few specific IPs/URLs by specifying several black list entries.
+ * <li>Allowing only some specific IPs/URLs by specifying several white lists entries.
+ * <li>Allowing a general range of IPs/URLs by specifying several general white list
+ * entries, that are then further refined by several specific black list exceptions
+ * </ul>
* <p>
- * An empty white list is treated as match all. If there is at least one entry in the
- * white list, then a request must match a white list entry. Black list entries are always
- * appied, so that even if an entry matches the white list, a black list entry will override.
+ * An empty white list is treated as match all. If there is at least one entry in
+ * the white list, then a request must match a white list entry. Black list entries
+ * are always applied, so that even if an entry matches the white list, a black list
+ * entry will override it.
+ * <p>
+ * Internet addresses may be specified as absolute address or as a combination of
+ * four octet wildcard specifications (a.b.c.d) that are defined as follows.
* </p>
+ * <pre>
+ * nnn - an absolute value (0-255)
+ * mmm-nnn - an inclusive range of absolute values,
+ * with following shorthand notations:
+ * nnn- => nnn-255
+ * -nnn => 0-nnn
+ * - => 0-255
+ * a,b,... - a list of wildcard specifications
+ * </pre>
+ * <p>
+ * Internet address specification is separated from the URI pattern using the "|" (pipe)
+ * character. URI patterns follow the servlet specification for simple * prefix and
+ * suffix wild cards (e.g. /, /foo, /foo/bar, /foo/bar/*, *.baz).
+ * <p>
+ * Earlier versions of the handler used internet address prefix wildcard specification
+ * to define a range of the internet addresses (e.g. 127., 10.10., 172.16.1.).
+ * They also used the first "/" character of the URI pattern to separate it from the
+ * internet address. Both of these features have been deprecated in the current version.
* <p>
- * Examples of match specifications are:
+ * Examples of the entry specifications are:
* <ul>
- * <li>10.1.2.3 - all requests from IP 10.1.2.3
- * <li>10.1.2.3/foo/bar - all requests from IP 10.1.2.3 to URI /foo/bar
- * <li>10.1.2.3/foo/* - all requests from IP 10.1.2.3 to URIs starting with /foo/
- * <li>10.1.2.3/*.html - all requests from IP 10.1.2.3 to URIs ending with .html
- * <li>10.1. - all requests from IPs starting with 10.1.
- * <li>10.1./foo/bar - all requests from IPs starting with 10.1. to URI /foo/bar
- * <li>10.1./foo/* - all requests from IPs starting with 10.1. to URIs starting with /foo/
+ * <li>10.10.1.2 - all requests from IP 10.10.1.2
+ * <li>10.10.1.2|/foo/bar - all requests from IP 10.10.1.2 to URI /foo/bar
+ * <li>10.10.1.2|/foo/* - all requests from IP 10.10.1.2 to URIs starting with /foo/
+ * <li>10.10.1.2|*.html - all requests from IP 10.10.1.2 to URIs ending with .html
+ * <li>10.10.0-255.0-255 - all requests from IPs within 10.10.0.0/16 subnet
+ * <li>10.10.0-.-255|/foo/bar - all requests from IPs within 10.10.0.0/16 subnet to URI /foo/bar
+ * <li>10.10.0-3,1,3,7,15|/foo/* - all requests from IPs addresses with last octet equal
+ * to 1,3,7,15 in subnet 10.10.0.0/22 to URIs starting with /foo/
* </ul>
* <p>
- * Typically, the black/white lists will be used in one of three modes:
- * <nl>
- * <li>Blocking a few specific IPs/URLs by specifying several black list entries.
- * <li>Allowing only some specific IPs/URLs by specifying several white lists entries.
- * <li>Allowing a general range of IPs/URLs by specifying serveral general white list
- * entries, that are then further refined by several specific black list exceptions
- * </ul>
- *
+ * Earlier versions of the handler used internet address prefix wildcard specification
+ * to define a range of the internet addresses (e.g. 127., 10.10., 172.16.1.).
+ * They also used the first "/" character of the URI pattern to separate it from the
+ * internet address. Both of these features have been deprecated in the current version.
*/
public class IPAccessHandler extends HandlerWrapper
{
- Map<String,PathMap> _whiteAddr = new HashMap<String, PathMap>();
- List<String> _whitePattern = new CopyOnWriteArrayList<String>();
- Map<String,PathMap> _blackAddr = new HashMap<String, PathMap>();
- List<String> _blackPattern = new CopyOnWriteArrayList<String>();
-
+ IPAddressMap<PathMap> _white = new IPAddressMap<PathMap>();
+ IPAddressMap<PathMap> _black = new IPAddressMap<PathMap>();
+
+ /* ------------------------------------------------------------ */
/**
+ * Creates new handler object
*/
public IPAccessHandler()
{
+ super();
}
- public void addBlack(String addrPath)
+ /* ------------------------------------------------------------ */
+ /**
+ * Creates new handler object and initializes white- and black-list
+ *
+ * @param white array of whitelist entries
+ * @param black array of blacklist entries
+ */
+ public IPAccessHandler(String[] white, String []black)
{
- add(addrPath, _blackAddr, _blackPattern);
+ super();
+
+ if (white != null && white.length > 0)
+ setWhite(white);
+ if (black != null && black.length > 0)
+ setBlack(black);
}
- public void addWhite(String addrPath)
+ /* ------------------------------------------------------------ */
+ /**
+ * Add a whitelist entry to an existing handler configuration
+ *
+ * @param entry new whitelist entry
+ */
+ public void addWhite(String entry)
{
- add(addrPath, _whiteAddr, _whitePattern);
+ add(entry, _white);
}
- public void setBlack(String[] addrPaths)
+ /* ------------------------------------------------------------ */
+ /**
+ * Add a blacklist entry to an existing handler configuration
+ *
+ * @param entry new blacklist entry
+ */
+ public void addBlack(String entry)
+ {
+ add(entry, _black);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Re-initialize the whitelist of existing handler object
+ *
+ * @param entries array of whitelist entries
+ */
+ public void setWhite(String[] entries)
{
- set(addrPaths, _blackAddr, _blackPattern);
+ set(entries, _white);
}
- public void setWhite(String[] addrPaths)
+ /* ------------------------------------------------------------ */
+ /**
+ * Re-initialize the blacklist of existing handler object
+ *
+ * @param entries array of blacklist entries
+ */
+ public void setBlack(String[] entries)
{
- set(addrPaths, _whiteAddr, _whitePattern);
+ set(entries, _black);
}
+ /* ------------------------------------------------------------ */
/**
+ * Checks the incoming request against the whitelist and blacklist
+ *
+ * @see org.eclipse.jetty.server.handler.HandlerWrapper#handle(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
@@ -123,78 +194,181 @@ public class IPAccessHandler extends HandlerWrapper
getHandler().handle(target,baseRequest, request, response);
}
+
- protected void add(String addrPath, Map<String,PathMap> addrMap, List<String> patternList)
+ /* ------------------------------------------------------------ */
+ /**
+ * Helper method to parse the new entry and add it to
+ * the specified address pattern map.
+ *
+ * @param entry new entry
+ * @param patternMap target address pattern map
+ */
+ protected void add(String entry, IPAddressMap<PathMap> patternMap)
{
- int idx = addrPath.indexOf('/');
- String addr = idx > 0 ? addrPath.substring(0,idx) : addrPath;
- String path = idx > 0 ? addrPath.substring(idx) : null;
- if (path!=null && path.length()>1 && path.charAt(1)=='*')
- path=path.substring(1);
-
- PathMap map = addrMap.get(addr);
- if (map==null)
+ if (entry != null && entry.length() > 0)
{
- map = new PathMap(true);
- addrMap.put(addr,map);
+ boolean deprecated = false;
+ int idx;
+ if (entry.indexOf('|') > 0 )
+ {
+ idx = entry.indexOf('|');
+ }
+ else
+ {
+ idx = entry.indexOf('/');
+ deprecated = (idx >= 0);
+ }
+
+ String addr = idx > 0 ? entry.substring(0,idx) : entry;
+ String path = idx > 0 ? entry.substring(idx) : "/*";
+
if (addr.endsWith("."))
- patternList.add(addr);
+ deprecated = true;
+ if (path!=null && (path.startsWith("|") || path.startsWith("/*.")))
+ path=path.substring(1);
+
+ PathMap pathMap = patternMap.get(addr);
+ if (pathMap == null)
+ {
+ pathMap = new PathMap(true);
+ patternMap.put(addr,pathMap);
+ }
+ if (path != null)
+ pathMap.put(path,path);
+
+ if (deprecated)
+ Log.debug(toString() +" - deprecated specification syntax: "+entry);
}
-
- if (path != null)
- map.put(path,path);
}
- protected void set(String[] addrPaths, Map<String,PathMap> addrMap, List<String> patternList)
+ /* ------------------------------------------------------------ */
+ /**
+ * Helper method to process a list of new entries and replace
+ * the content of the specified address pattern map
+ *
+ * @param entries new entries
+ * @param patternMap target address pattern map
+ */
+ protected void set(String[] entries, IPAddressMap<PathMap> patternMap)
{
- addrMap.clear();
- patternList.clear();
- for (String addrPath:addrPaths)
- add(addrPath, addrMap, patternList);
+ patternMap.clear();
+
+ if (entries != null && entries.length > 0)
+ {
+ for (String addrPath:entries)
+ {
+ add(addrPath, patternMap);
+ }
+ }
}
+ /* ------------------------------------------------------------ */
+ /**
+ * Check if specified request is allowed by current IPAccess rules.
+ *
+ * @param addr internet address
+ * @param path context path
+ * @return true if request is allowed
+ *
+ */
protected boolean isAddrUriAllowed(String addr, String path)
{
- if (_whiteAddr.size()>0)
+ if (_white.size()>0)
{
- PathMap white=_whiteAddr.get(addr);
+ boolean match = false;
- if (white==null || (white.size()>0 && white.match(path)==null))
+ Object whiteObj = _white.getLazyMatches(addr);
+ if (whiteObj != null)
{
- boolean match=false;
- for (String pattern:_whitePattern)
+ List whiteList = (whiteObj instanceof List) ? (List)whiteObj : Collections.singletonList(whiteObj);
+
+ for (Object entry: whiteList)
{
- if (addr.startsWith(pattern))
- {
- white=_whiteAddr.get(pattern);
- if (white!=null && white.size()>0 && white.match(path)!=null)
- {
- match=true;
- break;
- }
- }
+ PathMap pathMap = ((Map.Entry<String,PathMap>)entry).getValue();
+ if (match = (pathMap!=null && (pathMap.size()==0 || pathMap.match(path)!=null)))
+ break;
}
- if (!match)
- return false;
}
+
+ if (!match)
+ return false;
}
- PathMap black=_blackAddr.get(addr);
- if (black!=null && (black.size()==0 || black.match(path)!=null))
- return false;
-
- for (String pattern:_blackPattern)
+ if (_black.size() > 0)
{
- if (addr.startsWith(pattern))
+ Object blackObj = _black.getLazyMatches(addr);
+ if (blackObj != null)
{
- black=_blackAddr.get(pattern);
- if (black!=null && black.match(path)!=null)
- return false;
- break;
+ List blackList = (blackObj instanceof List) ? (List)blackObj : Collections.singletonList(blackObj);
+
+ for (Object entry: blackList)
+ {
+ PathMap pathMap = ((Map.Entry<String,PathMap>)entry).getValue();
+ if (pathMap!=null && (pathMap.size()==0 || pathMap.match(path)!=null))
+ return false;
+ }
}
}
return true;
}
-}
+ /* ------------------------------------------------------------ */
+ /**
+ * Dump the white- and black-list configurations when started
+ *
+ * @see org.eclipse.jetty.server.handler.HandlerWrapper#doStart()
+ */
+ @Override
+ protected void doStart()
+ throws Exception
+ {
+ super.doStart();
+
+ if (Log.isDebugEnabled())
+ {
+ System.err.println(dump());
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Dump the handler configuration
+ */
+ public String dump()
+ {
+ StringBuilder buf = new StringBuilder();
+
+ buf.append(toString());
+ buf.append(" WHITELIST:\n");
+ dump(buf, _white);
+ buf.append(toString());
+ buf.append(" BLACKLIST:\n");
+ dump(buf, _black);
+
+ return buf.toString();
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Dump a pattern map into a StringBuilder buffer
+ *
+ * @param buf buffer
+ * @param patternMap pattern map to dump
+ */
+ protected void dump(StringBuilder buf, IPAddressMap<PathMap> patternMap)
+ {
+ for (String addr: patternMap.keySet())
+ {
+ for (Object path: ((PathMap)patternMap.get(addr)).values())
+ {
+ buf.append("# ");
+ buf.append(addr);
+ buf.append("|");
+ buf.append(path);
+ buf.append("\n");
+ }
+ }
+ }
+ }
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java
new file mode 100644
index 0000000000..60ad6d10de
--- /dev/null
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ProxyHandler.java
@@ -0,0 +1,847 @@
+package org.eclipse.jetty.server.handler;
+
+import java.io.IOException;
+import java.net.InetSocketAddress;
+import java.nio.channels.ClosedChannelException;
+import java.nio.channels.SelectionKey;
+import java.nio.channels.SocketChannel;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.http.HttpMethods;
+import org.eclipse.jetty.http.HttpParser;
+import org.eclipse.jetty.io.Buffer;
+import org.eclipse.jetty.io.ConnectedEndPoint;
+import org.eclipse.jetty.io.Connection;
+import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.io.nio.IndirectNIOBuffer;
+import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
+import org.eclipse.jetty.io.nio.SelectorManager;
+import org.eclipse.jetty.server.Handler;
+import org.eclipse.jetty.server.HttpConnection;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.util.HostMap;
+import org.eclipse.jetty.util.component.LifeCycle;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.thread.ThreadPool;
+
+/**
+ * <p>Implementation of a tunneling proxy that supports HTTP CONNECT and transparent proxy.</p>
+ * <p>To work as CONNECT proxy, objects of this class must be instantiated using the no-arguments
+ * constructor, since the remote server information will be present in the CONNECT URI.</p>
+ * <p>To work as transparent proxy, objects of this class must be instantiated using the string
+ * argument constructor, passing the remote host address and port in the form {@code host:port}.</p>
+ *
+ * @version $Revision$ $Date$
+ */
+public class ProxyHandler extends HandlerWrapper
+{
+ private final Logger _logger = Log.getLogger(getClass().getName());
+ private final SelectorManager _selectorManager = new Manager();
+ private volatile int _connectTimeout = 5000;
+ private volatile int _writeTimeout = 30000;
+ private volatile ThreadPool _threadPool;
+ private volatile boolean _privateThreadPool;
+ private HostMap<String> _white = new HostMap<String>();
+ private HostMap<String> _black = new HostMap<String>();
+
+ public ProxyHandler()
+ {
+ this(null);
+ }
+
+ public ProxyHandler(String[] white, String[] black)
+ {
+ this(null, white, black);
+ }
+
+ public ProxyHandler(Handler handler)
+ {
+ setHandler(handler);
+ }
+
+ public ProxyHandler(Handler handler, String[] white, String[] black)
+ {
+ setHandler(handler);
+ set(white, _white);
+ set(black, _black);
+ }
+
+ /**
+ * @return the timeout, in milliseconds, to connect to the remote server
+ */
+ public int getConnectTimeout()
+ {
+ return _connectTimeout;
+ }
+
+ /**
+ * @param connectTimeout the timeout, in milliseconds, to connect to the remote server
+ */
+ public void setConnectTimeout(int connectTimeout)
+ {
+ _connectTimeout = connectTimeout;
+ }
+
+ /**
+ * @return the timeout, in milliseconds, to write data to a peer
+ */
+ public int getWriteTimeout()
+ {
+ return _writeTimeout;
+ }
+
+ /**
+ * @param writeTimeout the timeout, in milliseconds, to write data to a peer
+ */
+ public void setWriteTimeout(int writeTimeout)
+ {
+ _writeTimeout = writeTimeout;
+ }
+
+ @Override
+ public void setServer(Server server)
+ {
+ super.setServer(server);
+
+ server.getContainer().update(this,null,_selectorManager,"selectManager");
+
+ if (_privateThreadPool)
+ server.getContainer().update(this,null,_privateThreadPool,"threadpool",true);
+ else
+ _threadPool=server.getThreadPool();
+ }
+
+ /**
+ * @return the thread pool
+ */
+ public ThreadPool getThreadPool()
+ {
+ return _threadPool;
+ }
+
+ /**
+ * @param threadPool the thread pool
+ */
+ public void setThreadPool(ThreadPool threadPool)
+ {
+ if (getServer()!=null)
+ getServer().getContainer().update(this,_privateThreadPool?_threadPool:null,threadPool,"threadpool",true);
+ _privateThreadPool=threadPool!=null;
+ _threadPool=threadPool;
+ }
+
+ @Override
+ protected void doStart() throws Exception
+ {
+ super.doStart();
+
+ if (_threadPool==null)
+ {
+ _threadPool=getServer().getThreadPool();
+ _privateThreadPool=false;
+ }
+ if (_threadPool instanceof LifeCycle && !((LifeCycle)_threadPool).isRunning())
+ ((LifeCycle)_threadPool).start();
+
+ _selectorManager.start();
+ _threadPool.dispatch(new Runnable()
+ {
+ public void run()
+ {
+ while (isRunning())
+ {
+ try
+ {
+ _selectorManager.doSelect(0);
+ }
+ catch (IOException x)
+ {
+ _logger.warn("Unexpected exception", x);
+ }
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void doStop() throws Exception
+ {
+ _selectorManager.stop();
+
+ ThreadPool threadPool = _threadPool;
+ if (_privateThreadPool && _threadPool != null && threadPool instanceof LifeCycle)
+ ((LifeCycle)threadPool).stop();
+
+ super.doStop();
+ }
+
+ @Override
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
+ {
+ if (HttpMethods.CONNECT.equalsIgnoreCase(request.getMethod()))
+ {
+ _logger.debug("CONNECT request for {}", request.getRequestURI());
+ handleConnect(baseRequest, request, response, request.getRequestURI());
+ }
+ else
+ {
+ super.handle(target, baseRequest, request, response);
+ }
+ }
+
+ /**
+ * <p>Handles a CONNECT request.</p>
+ * <p>CONNECT requests may have authentication headers such as <code>Proxy-Authorization</code>
+ * that authenticate the client with the proxy.</p>
+ *
+ * @param baseRequest Jetty-specific http request
+ * @param request the http request
+ * @param response the http response
+ * @param serverAddress the remote server address in the form {@code host:port}
+ * @throws ServletException if an application error occurs
+ * @throws IOException if an I/O error occurs
+ */
+ protected void handleConnect(Request baseRequest, HttpServletRequest request, HttpServletResponse response, String serverAddress) throws ServletException, IOException
+ {
+ boolean proceed = handleAuthentication(request, response, serverAddress);
+ if (!proceed)
+ return;
+
+ String host = serverAddress;
+ int port = 80;
+ int colon = serverAddress.indexOf(':');
+ if (colon > 0)
+ {
+ host = serverAddress.substring(0, colon);
+ port = Integer.parseInt(serverAddress.substring(colon + 1));
+ }
+
+ if (!validateDestination(host))
+ {
+ Log.info("ProxyHandler: Forbidden destination "+host);
+ response.setStatus(HttpServletResponse.SC_FORBIDDEN);
+ baseRequest.setHandled(true);
+ return;
+ }
+
+ SocketChannel channel = connectToServer(request, host, port);
+
+ // Transfer unread data from old connection to new connection
+ // We need to copy the data to avoid races:
+ // 1. when this unread data is written and the server replies before the clientToProxy
+ // connection is installed (it is only installed after returning from this method)
+ // 2. when the client sends data before this unread data has been written.
+ HttpConnection httpConnection = HttpConnection.getCurrentConnection();
+ Buffer headerBuffer = ((HttpParser)httpConnection.getParser()).getHeaderBuffer();
+ Buffer bodyBuffer = ((HttpParser)httpConnection.getParser()).getBodyBuffer();
+ int length = headerBuffer == null ? 0 : headerBuffer.length();
+ length += bodyBuffer == null ? 0 : bodyBuffer.length();
+ IndirectNIOBuffer buffer = null;
+ if (length > 0)
+ {
+ buffer = new IndirectNIOBuffer(length);
+ if (headerBuffer != null)
+ {
+ buffer.put(headerBuffer);
+ headerBuffer.clear();
+ }
+ if (bodyBuffer != null)
+ {
+ buffer.put(bodyBuffer);
+ bodyBuffer.clear();
+ }
+ }
+
+ ConcurrentMap<String, Object> context = new ConcurrentHashMap<String, Object>();
+ prepareContext(request, context);
+
+ ClientToProxyConnection clientToProxy = prepareConnections(context, channel, buffer);
+
+ // CONNECT expects a 200 response
+ response.setStatus(HttpServletResponse.SC_OK);
+
+ // Prevent close
+ baseRequest.getConnection().getGenerator().setPersistent(true);
+
+ // Close to force last flush it so that the client receives it
+ response.getOutputStream().close();
+
+ upgradeConnection(request, response, clientToProxy);
+ }
+
+ private ClientToProxyConnection prepareConnections(ConcurrentMap<String, Object> context, SocketChannel channel, Buffer buffer)
+ {
+ HttpConnection httpConnection = HttpConnection.getCurrentConnection();
+ ProxyToServerConnection proxyToServer = newProxyToServerConnection(context, buffer);
+ ClientToProxyConnection clientToProxy = newClientToProxyConnection(context, channel, httpConnection.getEndPoint(), httpConnection.getTimeStamp());
+ clientToProxy.setConnection(proxyToServer);
+ proxyToServer.setConnection(clientToProxy);
+ return clientToProxy;
+ }
+
+ /**
+ * <p>Handles the authentication before setting up the tunnel to the remote server.</p>
+ * <p>The default implementation returns true.</p>
+ *
+ * @param request the HTTP request
+ * @param response the HTTP response
+ * @param address the address of the remote server in the form {@code host:port}.
+ * @return true to allow to connect to the remote host, false otherwise
+ * @throws ServletException to report a server error to the caller
+ * @throws IOException to report a server error to the caller
+ */
+ protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) throws ServletException, IOException
+ {
+ return true;
+ }
+
+ protected ClientToProxyConnection newClientToProxyConnection(ConcurrentMap<String, Object> context, SocketChannel channel, EndPoint endPoint, long timeStamp)
+ {
+ return new ClientToProxyConnection(context, channel, endPoint, timeStamp);
+ }
+
+ protected ProxyToServerConnection newProxyToServerConnection(ConcurrentMap<String, Object> context, Buffer buffer)
+ {
+ return new ProxyToServerConnection(context, buffer);
+ }
+
+ private SocketChannel connectToServer(HttpServletRequest request, String host, int port) throws IOException
+ {
+ SocketChannel channel = connect(request, host, port);
+ channel.configureBlocking(false);
+ return channel;
+ }
+
+ /**
+ * <p>Establishes a connection to the remote server.</p>
+ * @param request the HTTP request that initiated the tunnel
+ * @param host the host to connect to
+ * @param port the port to connect to
+ * @return a {@link SocketChannel} connected to the remote server
+ * @throws IOException if the connection cannot be established
+ */
+ protected SocketChannel connect(HttpServletRequest request, String host, int port) throws IOException
+ {
+ _logger.debug("Establishing connection to {}:{}", host, port);
+ // Connect to remote server
+ SocketChannel channel = SocketChannel.open();
+ channel.socket().setTcpNoDelay(true);
+ channel.socket().connect(new InetSocketAddress(host, port), getConnectTimeout());
+ _logger.debug("Established connection to {}:{}", host, port);
+ return channel;
+ }
+
+ protected void prepareContext(HttpServletRequest request, ConcurrentMap<String, Object> context)
+ {
+ }
+
+ private void upgradeConnection(HttpServletRequest request, HttpServletResponse response, Connection connection) throws IOException
+ {
+ // Set the new connection as request attribute and change the status to 101
+ // so that Jetty understands that it has to upgrade the connection
+ request.setAttribute("org.eclipse.jetty.io.Connection", connection);
+ response.setStatus(HttpServletResponse.SC_SWITCHING_PROTOCOLS);
+ _logger.debug("Upgraded connection to {}", connection);
+ }
+
+ private void register(SocketChannel channel, ProxyToServerConnection proxyToServer) throws IOException
+ {
+ _selectorManager.register(channel, proxyToServer);
+ proxyToServer.waitReady(_connectTimeout);
+ }
+
+ /**
+ * <p>Reads (with non-blocking semantic) into the given {@code buffer} from the given {@code endPoint}.</p>
+ * @param endPoint the endPoint to read from
+ * @param buffer the buffer to read data into
+ * @param context the context information related to the connection
+ * @return the number of bytes read (possibly 0 since the read is non-blocking)
+ * or -1 if the channel has been closed remotely
+ * @throws IOException if the endPoint cannot be read
+ */
+ protected int read(EndPoint endPoint, Buffer buffer, ConcurrentMap<String, Object> context) throws IOException
+ {
+ return endPoint.fill(buffer);
+ }
+
+ /**
+ * <p>Writes (with blocking semantic) the given buffer of data onto the given endPoint.</p>
+ *
+ * @param endPoint the endPoint to write to
+ * @param buffer the buffer to write
+ * @param context the context information related to the connection
+ * @throws IOException if the buffer cannot be written
+ * @return the number of bytes written
+ */
+ protected int write(EndPoint endPoint, Buffer buffer, ConcurrentMap<String, Object> context) throws IOException
+ {
+ if (buffer == null)
+ return 0;
+
+ int length = buffer.length();
+ StringBuilder builder = new StringBuilder();
+ int written = endPoint.flush(buffer);
+ builder.append(written);
+ buffer.compact();
+ if (!endPoint.isBlocking())
+ {
+ while (buffer.space() == 0)
+ {
+ boolean ready = endPoint.blockWritable(getWriteTimeout());
+ if (!ready)
+ throw new IOException("Write timeout");
+
+ written = endPoint.flush(buffer);
+ builder.append("+").append(written);
+ buffer.compact();
+ }
+ }
+ _logger.debug("Written {}/{} bytes {}", builder, length, endPoint);
+ return length;
+ }
+
+ private class Manager extends SelectorManager
+ {
+ @Override
+ protected SocketChannel acceptChannel(SelectionKey key) throws IOException
+ {
+ // This is a client-side selector manager
+ throw new IllegalStateException();
+ }
+
+ @Override
+ protected SelectChannelEndPoint newEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey selectionKey) throws IOException
+ {
+ return new SelectChannelEndPoint(channel, selectSet, selectionKey);
+ }
+
+ @Override
+ protected Connection newConnection(SocketChannel channel, SelectChannelEndPoint endpoint)
+ {
+ ProxyToServerConnection proxyToServer = (ProxyToServerConnection)endpoint.getSelectionKey().attachment();
+ proxyToServer.setTimeStamp(System.currentTimeMillis());
+ proxyToServer.setEndPoint(endpoint);
+ return proxyToServer;
+ }
+
+ @Override
+ protected void endPointOpened(SelectChannelEndPoint endpoint)
+ {
+ ProxyToServerConnection proxyToServer = (ProxyToServerConnection)endpoint.getSelectionKey().attachment();
+ proxyToServer.ready();
+ }
+
+ @Override
+ public boolean dispatch(Runnable task)
+ {
+ return _threadPool.dispatch(task);
+ }
+
+ @Override
+ protected void endPointClosed(SelectChannelEndPoint endpoint)
+ {
+ }
+
+ @Override
+ protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection)
+ {
+ }
+ }
+
+ public class ProxyToServerConnection implements Connection
+ {
+ private final CountDownLatch _ready = new CountDownLatch(1);
+ private final Buffer _buffer = new IndirectNIOBuffer(1024);
+ private final ConcurrentMap<String, Object> _context;
+ private volatile Buffer _data;
+ private volatile ClientToProxyConnection _toClient;
+ private volatile long _timestamp;
+ private volatile SelectChannelEndPoint _endPoint;
+
+ public ProxyToServerConnection(ConcurrentMap<String, Object> context, Buffer data)
+ {
+ _context = context;
+ _data = data;
+ }
+
+ public Connection handle() throws IOException
+ {
+ _logger.debug("ProxyToServer: begin reading from server");
+ try
+ {
+ if (_data != null)
+ {
+ int written = write(_endPoint, _data, _context);
+ _logger.debug("ProxyToServer: written to server {} bytes", written);
+ _data = null;
+ }
+
+ while (true)
+ {
+ int read = read(_endPoint, _buffer, _context);
+
+ if (read == -1)
+ {
+ _logger.debug("ProxyToServer: server closed connection {}", _endPoint);
+ close();
+ break;
+ }
+
+ if (read == 0)
+ break;
+
+ _logger.debug("ProxyToServer: read from server {} bytes {}", read, _endPoint);
+ int written = write(_toClient._endPoint, _buffer, _context);
+ _logger.debug("ProxyToServer: written to client {} bytes", written);
+ }
+ return this;
+ }
+ catch (IOException x)
+ {
+ _logger.warn("ProxyToServer: Unexpected exception", x);
+ close();
+ throw x;
+ }
+ catch (RuntimeException x)
+ {
+ _logger.warn("ProxyToServer: Unexpected exception", x);
+ close();
+ throw x;
+ }
+ finally
+ {
+ _logger.debug("ProxyToServer: end reading from server");
+ }
+ }
+
+ public void setConnection(ClientToProxyConnection connection)
+ {
+ _toClient = connection;
+ }
+
+ public long getTimeStamp()
+ {
+ return _timestamp;
+ }
+
+ public void setTimeStamp(long timestamp)
+ {
+ _timestamp = timestamp;
+ }
+
+ public void setEndPoint(SelectChannelEndPoint endpoint)
+ {
+ _endPoint = endpoint;
+ _logger.debug("ProxyToServer: {}", _endPoint);
+ }
+
+ public boolean isIdle()
+ {
+ return false;
+ }
+
+ public boolean isSuspended()
+ {
+ return false;
+ }
+
+ public void ready()
+ {
+ _ready.countDown();
+ }
+
+ public void waitReady(long timeout) throws IOException
+ {
+ try
+ {
+ _ready.await(timeout, TimeUnit.MILLISECONDS);
+ }
+ catch (final InterruptedException x)
+ {
+ throw new IOException(){{initCause(x);}};
+ }
+ }
+
+ public void closeClient() throws IOException
+ {
+ _toClient.closeClient();
+ }
+
+ public void closeServer() throws IOException
+ {
+ _endPoint.close();
+ }
+
+ public void close()
+ {
+ try
+ {
+ closeClient();
+ }
+ catch (IOException x)
+ {
+ _logger.debug("ProxyToServer: Unexpected exception closing the client", x);
+ }
+
+ try
+ {
+ closeServer();
+ }
+ catch (IOException x)
+ {
+ _logger.debug("ProxyToServer: Unexpected exception closing the server", x);
+ }
+ }
+ }
+
+ public class ClientToProxyConnection implements Connection
+ {
+ private final Buffer _buffer = new IndirectNIOBuffer(1024);
+ private final ConcurrentMap<String, Object> _context;
+ private final SocketChannel _channel;
+ private final EndPoint _endPoint;
+ private final long _timestamp;
+ private volatile ProxyToServerConnection _toServer;
+ private boolean _firstTime = true;
+
+ public ClientToProxyConnection(ConcurrentMap<String, Object> context, SocketChannel channel, EndPoint endPoint, long timestamp)
+ {
+ _context = context;
+ _channel = channel;
+ _endPoint = endPoint;
+ _timestamp = timestamp;
+ _logger.debug("ClientToProxy: {}", _endPoint);
+ }
+
+ public Connection handle() throws IOException
+ {
+ _logger.debug("ClientToProxy: begin reading from client");
+ try
+ {
+ if (_firstTime)
+ {
+ _firstTime = false;
+ register(_channel, _toServer);
+ _logger.debug("ClientToProxy: registered channel {} with connection {}", _channel, _toServer);
+ }
+
+ while (true)
+ {
+ int read = read(_endPoint, _buffer, _context);
+
+ if (read == -1)
+ {
+ _logger.debug("ClientToProxy: client closed connection {}", _endPoint);
+ close();
+ break;
+ }
+
+ if (read == 0)
+ break;
+
+ _logger.debug("ClientToProxy: read from client {} bytes {}", read, _endPoint);
+ int written = write(_toServer._endPoint, _buffer, _context);
+ _logger.debug("ClientToProxy: written to server {} bytes", written);
+ }
+ return this;
+ }
+ catch (ClosedChannelException x)
+ {
+ _logger.debug("ClientToProxy",x);
+ closeServer();
+ throw x;
+ }
+ catch (IOException x)
+ {
+ _logger.warn("ClientToProxy", x);
+ close();
+ throw x;
+ }
+ catch (RuntimeException x)
+ {
+ _logger.warn("ClientToProxy", x);
+ close();
+ throw x;
+ }
+ finally
+ {
+ _logger.debug("ClientToProxy: end reading from client");
+ }
+ }
+
+ public long getTimeStamp()
+ {
+ return _timestamp;
+ }
+
+ public boolean isIdle()
+ {
+ return false;
+ }
+
+ public boolean isSuspended()
+ {
+ return false;
+ }
+
+ public void setConnection(ProxyToServerConnection connection)
+ {
+ _toServer = connection;
+ }
+
+ public void closeClient() throws IOException
+ {
+ _endPoint.close();
+ }
+
+ public void closeServer() throws IOException
+ {
+ _toServer.closeServer();
+ }
+
+ public void close()
+ {
+ try
+ {
+ closeClient();
+ }
+ catch (IOException x)
+ {
+ _logger.debug("ClientToProxy: Unexpected exception closing the client", x);
+ }
+
+ try
+ {
+ closeServer();
+ }
+ catch (IOException x)
+ {
+ _logger.debug("ClientToProxy: Unexpected exception closing the server", x);
+ }
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Add a whitelist entry to an existing handler configuration
+ *
+ * @param entry new whitelist entry
+ */
+ public void addWhite(String entry)
+ {
+ add(entry, _white);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Add a blacklist entry to an existing handler configuration
+ *
+ * @param entry new blacklist entry
+ */
+ public void addBlack(String entry)
+ {
+ add(entry, _black);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Re-initialize the whitelist of existing handler object
+ *
+ * @param entries array of whitelist entries
+ */
+ public void setWhite(String[] entries)
+ {
+ set(entries, _white);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Re-initialize the blacklist of existing handler object
+ *
+ * @param entries array of blacklist entries
+ */
+ public void setBlack(String[] entries)
+ {
+ set(entries, _black);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Helper method to process a list of new entries and replace
+ * the content of the specified host map
+ *
+ * @param entries new entries
+ * @param patternMap target host map
+ */
+ protected void set(String[] entries, HostMap<String> hostMap)
+ {
+ hostMap.clear();
+
+ if (entries != null && entries.length > 0)
+ {
+ for (String addrPath:entries)
+ {
+ add(addrPath, hostMap);
+ }
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Helper method to process the new entry and add it to
+ * the specified host map.
+ *
+ * @param entry new entry
+ * @param patternMap target host map
+ */
+ private void add(String entry, HostMap<String> hostMap)
+ {
+ if (entry != null && entry.length() > 0)
+ {
+ entry = entry.trim();
+ if (hostMap.get(entry) == null)
+ {
+ hostMap.put(entry,entry);
+ }
+ }
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Check the request hostname against white- and blacklist.
+ *
+ * @param host hostname to check
+ * @return true if hostname is allowed to be proxied
+ */
+ public boolean validateDestination(String host)
+ {
+ if (_white.size()>0)
+ {
+ Object whiteObj = _white.getLazyMatches(host);
+ if (whiteObj == null)
+ {
+ return false;
+ }
+ }
+
+ if (_black.size() > 0)
+ {
+ Object blackObj = _black.getLazyMatches(host);
+ if (blackObj != null)
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java
index 61d949da32..76ee4391a0 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/RequestLogHandler.java
@@ -20,6 +20,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
+import org.eclipse.jetty.server.AsyncContinuation;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Response;
@@ -47,9 +48,24 @@ public class RequestLogHandler extends HandlerWrapper
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
- super.handle(target, baseRequest, request, response);
- if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()) && _requestLog!=null)
- _requestLog.log((Request)request, (Response)response);
+ AsyncContinuation continuation = baseRequest.getAsyncContinuation();
+ if (!continuation.isInitial())
+ {
+ baseRequest.setDispatchTime(System.currentTimeMillis());
+ }
+
+ try
+ {
+ super.handle(target, baseRequest, request, response);
+ }
+ finally
+ {
+ if (_requestLog != null && DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
+ {
+ _requestLog.log(baseRequest, (Response)response);
+ }
+
+ }
}
/* ------------------------------------------------------------ */
@@ -131,6 +147,5 @@ public class RequestLogHandler extends HandlerWrapper
if (_requestLog!=null)
_requestLog.stop();
}
-
}
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 2bbc84f93d..51ba08e04a 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
@@ -4,11 +4,11 @@
// 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
+// 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.
+// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server.handler;
@@ -16,7 +16,6 @@ package org.eclipse.jetty.server.handler;
import java.io.IOException;
import java.io.OutputStream;
import java.net.MalformedURLException;
-
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@@ -33,7 +32,6 @@ import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.handler.ContextHandler.Context;
-import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.FileResource;
@@ -42,12 +40,12 @@ import org.eclipse.jetty.util.resource.Resource;
/* ------------------------------------------------------------ */
/** Resource Handler.
- *
+ *
* This handle will serve static content and handle If-Modified-Since headers.
* No caching is done.
* Requests that cannot be handled are let pass (Eg no 404's)
- *
- *
+ *
+ *
* @org.apache.xbean.XBean
*/
public class ResourceHandler extends AbstractHandler
@@ -90,7 +88,7 @@ public class ResourceHandler extends AbstractHandler
/**
* Set if resource aliases (eg symlink, 8.3 names, case insensitivity) are allowed.
* Allowing aliases can significantly increase security vulnerabilities.
- * If this handler is deployed inside a ContextHandler, then the
+ * If this handler is deployed inside a ContextHandler, then the
* {@link ContextHandler#isAliases()} takes precedent.
* @param aliases True if aliases are supported.
*/
@@ -124,13 +122,13 @@ public class ResourceHandler extends AbstractHandler
{
Context scontext = ContextHandler.getCurrentContext();
_context = (scontext==null?null:scontext.getContextHandler());
-
+
if (_context!=null)
_aliases=_context.isAliases();
-
+
if (!_aliases && !FileResource.getCheckAliases())
throw new IllegalStateException("Alias checking disabled");
-
+
super.doStart();
}
@@ -156,12 +154,12 @@ public class ResourceHandler extends AbstractHandler
return _baseResource.toString();
}
-
+
/* ------------------------------------------------------------ */
/**
* @param base The resourceBase to set.
*/
- public void setBaseResource(Resource base)
+ public void setBaseResource(Resource base)
{
_baseResource=base;
}
@@ -170,7 +168,7 @@ public class ResourceHandler extends AbstractHandler
/**
* @param resourceBase The base resource as a string.
*/
- public void setResourceBase(String resourceBase)
+ public void setResourceBase(String resourceBase)
{
try
{
@@ -203,18 +201,18 @@ public class ResourceHandler extends AbstractHandler
}
/* ------------------------------------------------------------ */
- /*
+ /*
*/
public Resource getResource(String path) throws MalformedURLException
{
if (path==null || !path.startsWith("/"))
throw new MalformedURLException(path);
-
+
Resource base = _baseResource;
if (base==null)
{
if (_context==null)
- return null;
+ return null;
base=_context.getBaseResource();
if (base==null)
return null;
@@ -229,7 +227,7 @@ public class ResourceHandler extends AbstractHandler
{
Log.ignore(e);
}
-
+
return null;
}
@@ -254,7 +252,7 @@ public class ResourceHandler extends AbstractHandler
{
_welcomeFiles=welcomeFiles;
}
-
+
/* ------------------------------------------------------------ */
protected Resource getWelcome(Resource directory) throws MalformedURLException, IOException
{
@@ -269,14 +267,14 @@ public class ResourceHandler extends AbstractHandler
}
/* ------------------------------------------------------------ */
- /*
+ /*
* @see org.eclipse.jetty.server.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
*/
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
if (baseRequest.isHandled())
return;
-
+
boolean skipContentBody = false;
if(!HttpMethods.GET.equals(request.getMethod()))
{
@@ -284,9 +282,9 @@ public class ResourceHandler extends AbstractHandler
return;
skipContentBody = true;
}
-
+
Resource resource=getResource(request);
-
+
if (resource==null || !resource.exists())
return;
if (!_aliases && resource.getAlias()!=null)
@@ -297,7 +295,7 @@ public class ResourceHandler extends AbstractHandler
// We are going to server something
baseRequest.setHandled(true);
-
+
if (resource.isDirectory())
{
if (!request.getPathInfo().endsWith(URIUtil.SLASH))
@@ -305,7 +303,7 @@ public class ResourceHandler extends AbstractHandler
response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getRequestURI(),URIUtil.SLASH)));
return;
}
-
+
Resource welcome=getWelcome(resource);
if (welcome!=null && welcome.exists())
resource=welcome;
@@ -316,7 +314,7 @@ public class ResourceHandler extends AbstractHandler
return;
}
}
-
+
// set some headers
long last_modified=resource.lastModified();
if (last_modified>0)
@@ -328,11 +326,11 @@ public class ResourceHandler extends AbstractHandler
return;
}
}
-
+
Buffer mime=_mimeTypes.getMimeByExtension(resource.toString());
if (mime==null)
mime=_mimeTypes.getMimeByExtension(request.getPathInfo());
-
+
// set the headers
doResponseHeaders(response,resource,mime!=null?mime.toString():null);
response.setDateHeader(HttpHeaders.LAST_MODIFIED,last_modified);
@@ -342,7 +340,7 @@ public class ResourceHandler extends AbstractHandler
OutputStream out =null;
try {out = response.getOutputStream();}
catch(IllegalStateException e) {out = new WriterOutputStream(response.getWriter());}
-
+
// See if a short direct method can be used?
if (out instanceof HttpConnection.Output)
{
@@ -369,7 +367,7 @@ public class ResourceHandler extends AbstractHandler
else
response.sendError(HttpStatus.FORBIDDEN_403);
}
-
+
/* ------------------------------------------------------------ */
/** Set the response headers.
* This method is called to set the response headers such as content type and content length.
@@ -384,25 +382,25 @@ public class ResourceHandler extends AbstractHandler
response.setContentType(mimeType);
long length=resource.length();
-
+
if (response instanceof Response)
{
HttpFields fields = ((Response)response).getHttpFields();
if (length>0)
fields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER,length);
-
+
if (_cacheControl!=null)
fields.put(HttpHeaders.CACHE_CONTROL_BUFFER,_cacheControl);
}
else
{
if (length>0)
- response.setHeader(HttpHeaders.CONTENT_LENGTH,TypeUtil.toString(length));
-
+ response.setHeader(HttpHeaders.CONTENT_LENGTH,Long.toString(length));
+
if (_cacheControl!=null)
response.setHeader(HttpHeaders.CACHE_CONTROL,_cacheControl.toString());
}
-
+
}
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java
index ae3154c3b7..d4ff318c7a 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ScopedHandler.java
@@ -134,7 +134,7 @@ public abstract class ScopedHandler extends HandlerWrapper
throws IOException, ServletException
{
// this method has been manually inlined in several locations, but
- // is called protected by an in(false), so your IDE can find those
+ // is called protected by an if(never()), so your IDE can find those
// locations if this code is changed.
if (_nextScope!=null)
_nextScope.doScope(target,baseRequest,request, response);
@@ -158,7 +158,7 @@ public abstract class ScopedHandler extends HandlerWrapper
public final void nextHandle(String target, final Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
// this method has been manually inlined in several locations, but
- // is called protected by an in(false), so your IDE can find those
+ // is called protected by an if(never()), so your IDE can find those
// locations if this code is changed.
if (_nextScope!=null && _nextScope==_handler)
_nextScope.doHandle(target,baseRequest,request, response);
@@ -166,4 +166,10 @@ public abstract class ScopedHandler extends HandlerWrapper
_handler.handle(target,baseRequest, request, response);
}
+ /* ------------------------------------------------------------ */
+ protected boolean never()
+ {
+ return false;
+ }
+
}
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/nio/BlockingChannelConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/nio/BlockingChannelConnector.java
index 1973e0a4d0..3927cb1caf 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/nio/BlockingChannelConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/nio/BlockingChannelConnector.java
@@ -100,14 +100,8 @@ public class BlockingChannelConnector extends AbstractNIOConnector
public void customize(EndPoint endpoint, Request request)
throws IOException
{
- ConnectorEndPoint connection = (ConnectorEndPoint)endpoint;
- if (connection._sotimeout!=_maxIdleTime)
- {
- connection._sotimeout=_maxIdleTime;
- ((SocketChannel)endpoint.getTransport()).socket().setSoTimeout(_maxIdleTime);
- }
-
super.customize(endpoint, request);
+ endpoint.setMaxIdleTime(_maxIdleTime);
configure(((SocketChannel)endpoint.getTransport()).socket());
}
@@ -130,12 +124,12 @@ public class BlockingChannelConnector extends AbstractNIOConnector
int _sotimeout;
ConnectorEndPoint(ByteChannel channel)
+ throws IOException
{
- super(channel);
+ super(channel,BlockingChannelConnector.this._maxIdleTime);
_connection = new HttpConnection(BlockingChannelConnector.this,this,getServer());
}
-
/* ------------------------------------------------------------ */
/** Get the connection.
* @return the connection
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/nio/SelectChannelConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/nio/SelectChannelConnector.java
index 175bf6e176..40cb4f7fa0 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/nio/SelectChannelConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/nio/SelectChannelConnector.java
@@ -4,11 +4,11 @@
// 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
+// 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.
+// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server.nio;
@@ -20,6 +20,7 @@ import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
+import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
@@ -44,27 +45,25 @@ import org.eclipse.jetty.util.thread.Timeout.Task;
* This connector is best used when there are a many connections that have idle periods.
* </p>
* <p>
- * When used with {@link org.eclipse.jetty.util.ajax.Continuation}, threadless waits are supported. When
- * a filter or servlet calls getEvent on a Continuation, a {@link org.eclipse.jetty.server.RetryRequest}
- * runtime exception is thrown to allow the thread to exit the current request handling. Jetty will
- * catch this exception and will not send a response to the client. Instead the thread is released
- * and the Continuation is placed on the timer queue. If the Continuation timeout expires, or it's
+ * When used with {@link org.eclipse.jetty.continuation.Continuation}, threadless waits are supported.
+ * If a filter or servlet returns after calling {@link Continuation#suspend()} or when a
+ * runtime exception is thrown from a call to {@link Continuation#undispatch()}, Jetty will
+ * will not send a response to the client. Instead the thread is released and the Continuation is
+ * placed on the timer queue. If the Continuation timeout expires, or it's
* resume method is called, then the request is again allocated a thread and the request is retried.
* The limitation of this approach is that request content is not available on the retried request,
* thus if possible it should be read after the continuation or saved as a request attribute or as the
* associated object of the Continuation instance.
* </p>
- *
- * @org.apache.xbean.XBean element="nioConnector" description="Creates an NIO based socket connector"
- *
- *
*
+ * @org.apache.xbean.XBean element="nioConnector" description="Creates an NIO based socket connector"
*/
-public class SelectChannelConnector extends AbstractNIOConnector
+public class SelectChannelConnector extends AbstractNIOConnector
{
protected ServerSocketChannel _acceptChannel;
private int _lowResourcesConnections;
private int _lowResourcesMaxIdleTime;
+ private int _localPort=-1;
private final SelectorManager _manager = new SelectorManager()
{
@@ -99,7 +98,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
// TODO handle max connections and low resources
connectionOpened(endpoint.getConnection());
}
-
+
@Override
protected void endPointUpgraded(ConnectedEndPoint endpoint, Connection oldConnection)
{
@@ -118,23 +117,23 @@ public class SelectChannelConnector extends AbstractNIOConnector
return SelectChannelConnector.this.newEndPoint(channel,selectSet,sKey);
}
};
-
+
/* ------------------------------------------------------------------------------- */
/**
* Constructor.
- *
+ *
*/
public SelectChannelConnector()
{
}
-
+
/* ------------------------------------------------------------ */
@Override
public void accept(int acceptorID) throws IOException
{
_manager.doSelect(acceptorID);
}
-
+
/* ------------------------------------------------------------ */
public void close() throws IOException
{
@@ -154,9 +153,10 @@ public class SelectChannelConnector extends AbstractNIOConnector
if (_acceptChannel != null)
_acceptChannel.close();
_acceptChannel = null;
+ _localPort=-2;
}
}
-
+
/* ------------------------------------------------------------------------------- */
@Override
public void customize(EndPoint endpoint, Request request) throws IOException
@@ -166,7 +166,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
request.setTimeStamp(cep.getSelectSet().getNow());
super.customize(endpoint, request);
}
-
+
/* ------------------------------------------------------------------------------- */
@Override
public void persist(EndPoint endpoint) throws IOException
@@ -186,9 +186,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
{
synchronized(this)
{
- if (_acceptChannel==null || !_acceptChannel.isOpen())
- return -1;
- return _acceptChannel.socket().getLocalPort();
+ return _localPort;
}
}
@@ -209,12 +207,13 @@ public class SelectChannelConnector extends AbstractNIOConnector
InetSocketAddress addr = getHost()==null?new InetSocketAddress(getPort()):new InetSocketAddress(getHost(),getPort());
_acceptChannel.socket().bind(addr,getAcceptQueueSize());
- if (_acceptChannel.socket().getLocalPort()==-1)
+ _localPort=_acceptChannel.socket().getLocalPort();
+ if (_localPort<=0)
throw new IOException("Server channel not bound");
-
+
// Set to non blocking mode
_acceptChannel.configureBlocking(false);
-
+
}
}
}
@@ -241,7 +240,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
* Set the number of connections, which if exceeded places this manager in low resources state.
* This is not an exact measure as the connection count is averaged over the select sets.
* @param lowResourcesConnections the number of connections
- * @see {@link #setLowResourcesMaxIdleTime(int)}
+ * @see #setLowResourcesMaxIdleTime(int)
*/
public void setLowResourcesConnections(int lowResourcesConnections)
{
@@ -264,16 +263,16 @@ public class SelectChannelConnector extends AbstractNIOConnector
* than {@link #getLowResourcesConnections()} connections. This allows the server to rapidly close idle connections
* in order to gracefully handle high load situations.
* @param lowResourcesMaxIdleTime the period in ms that a connection is allowed to be idle when resources are low.
- * @see {@link #setMaxIdleTime(long)}
+ * @see #setMaxIdleTime(int)
*/
@Override
public void setLowResourcesMaxIdleTime(int lowResourcesMaxIdleTime)
{
_lowResourcesMaxIdleTime=lowResourcesMaxIdleTime;
- super.setLowResourcesMaxIdleTime(lowResourcesMaxIdleTime);
+ super.setLowResourcesMaxIdleTime(lowResourcesMaxIdleTime);
}
-
+
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.server.AbstractConnector#doStart()
@@ -297,7 +296,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
*/
@Override
protected void doStop() throws Exception
- {
+ {
super.doStop();
}
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 f4a2ff6fff..0f7a305a0e 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
@@ -56,12 +56,9 @@ import org.eclipse.jetty.util.statistic.SampleStatistic;
* SessionManager interface provides the majority of the handling required to
* implement a SessionManager. Concrete implementations of SessionManager based
* on AbstractSessionManager need only implement the newSession method to return
- * a specialized version of the Session inner class that provides an attribute
+ * a specialised version of the Session inner class that provides an attribute
* Map.
* <p>
- * If the property
- * org.eclipse.jetty.servlet.AbstractSessionManager.23Notifications is set to
- * true, the 2.3 servlet spec notification style will be used.
*
*/
public abstract class AbstractSessionManager extends AbstractLifeCycle implements SessionManager
@@ -97,7 +94,8 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
protected int _maxCookieAge=-1;
protected int _refreshCookieAge;
protected boolean _nodeIdInSessionId;
-
+ protected boolean _checkingRemoteSessionIdEncoding;
+ protected String _sessionComment;
public Set<SessionTrackingMode> _sessionTrackingModes;
@@ -128,7 +126,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
)
)
{
- HttpCookie cookie=getSessionCookie(session,_context.getContextPath(),secure);
+ HttpCookie cookie=getSessionCookie(session,_context==null?"/":(_context.getContextPath()),secure);
s.cookieSet();
s.setIdChanged(false);
return cookie;
@@ -209,6 +207,10 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
// set up the sessionPath if it isn't already
if (_sessionPath==null)
_sessionPath=_context.getInitParameter(SessionManager.__SessionPathProperty);
+
+ tmp=_context.getInitParameter(SessionManager.__CheckRemoteSessionEncoding);
+ if (tmp!=null)
+ _checkingRemoteSessionIdEncoding=Boolean.parseBoolean(tmp);
}
super.doStart();
@@ -226,6 +228,15 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
}
/* ------------------------------------------------------------ */
+ /**
+ * @return Returns the httpOnly.
+ */
+ public boolean getHttpOnly()
+ {
+ return _httpOnly;
+ }
+
+ /* ------------------------------------------------------------ */
public HttpSession getHttpSession(String nodeId)
{
String cluster_id = getIdManager().getClusterId(nodeId);
@@ -261,7 +272,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
/**
- * @see getSessionsMax()
+ * @see #getSessionsMax()
*/
@Deprecated
public int getMaxSessions()
@@ -299,7 +310,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
/**
- * @see getSessionsMin()
+ * @deprecated always returns 0. no replacement available.
*/
@Deprecated
public int getMinSessions()
@@ -318,16 +329,35 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
{
if (isUsingCookies())
{
+ String sessionPath = (_sessionPath==null) ? contextPath : _sessionPath;
+ sessionPath = (sessionPath==null||sessionPath.length()==0) ? "/" : sessionPath;
String id = getNodeId(session);
- HttpCookie cookie=new HttpCookie(
- _sessionCookie,
- id,
- _sessionDomain,
- (contextPath==null||contextPath.length()==0)?"/":contextPath,
- _cookieConfig.getMaxAge(),
- _cookieConfig.isHttpOnly(),
- requestIsSecure&&_cookieConfig.isSecure());
-
+ HttpCookie cookie = null;
+ if (_sessionComment == null)
+ {
+ cookie = new HttpCookie(
+ _sessionCookie,
+ id,
+ _sessionDomain,
+ sessionPath,
+ _cookieConfig.getMaxAge(),
+ _cookieConfig.isHttpOnly(),
+ _cookieConfig.isSecure());
+ }
+ else
+ {
+ cookie = new HttpCookie(
+ _sessionCookie,
+ id,
+ _sessionDomain,
+ sessionPath,
+ _cookieConfig.getMaxAge(),
+ _cookieConfig.isHttpOnly(),
+ _cookieConfig.isSecure(),
+ _sessionComment,
+ 1);
+ }
+
return cookie;
}
return null;
@@ -344,7 +374,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
/**
- * @deprecated. Need to review if it is needed.
+ * @deprecated Need to review if it is needed.
*/
public abstract Map getSessionMap();
@@ -410,7 +440,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
/**
- * @see statsReset()
+ * @see #statsReset()
*/
@Deprecated
public void resetStats()
@@ -530,7 +560,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/**
* Create a new session instance
* @param request
- * @return
+ * @return the new session
*/
protected abstract Session newSession(HttpServletRequest request);
@@ -671,7 +701,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
@Override
public String getComment()
{
- return null;
+ return _sessionComment;
}
@Override
@@ -713,7 +743,7 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
@Override
public void setComment(String comment)
{
- // TODO
+ _sessionComment = comment;
}
@Override
@@ -784,6 +814,24 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
/* ------------------------------------------------------------ */
/**
+ * @see org.eclipse.jetty.server.SessionManager#isCheckingRemoteSessionIdEncoding()
+ */
+ public boolean isCheckingRemoteSessionIdEncoding()
+ {
+ return _checkingRemoteSessionIdEncoding;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @see org.eclipse.jetty.server.SessionManager#setCheckingRemoteSessionIdEncoding(boolean)
+ */
+ public void setCheckingRemoteSessionIdEncoding(boolean remote)
+ {
+ _checkingRemoteSessionIdEncoding=remote;
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
* Null returning implementation of HttpSessionContext
*
*
@@ -830,12 +878,10 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
}
/* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
- /* ------------------------------------------------------------ */
/**
*
* <p>
- * Implements {@link javax.servlet.HttpSession} from the {@link javax.servlet} package.
+ * Implements {@link javax.servlet.http.HttpSession} from the <code>javax.servlet</code> package.
* </p>
*
*
@@ -1047,10 +1093,13 @@ public abstract class AbstractSessionManager extends AbstractLifeCycle implement
// Notify listeners and unbind values
synchronized (this)
{
- if (_requests<=0)
- doInvalidate();
- else
- _doInvalidate=true;
+ if (!_invalid)
+ {
+ if (_requests<=0)
+ doInvalidate();
+ else
+ _doInvalidate=true;
+ }
}
}
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 bf227dd885..830cbfc7c5 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
@@ -48,6 +48,7 @@ public class HashSessionIdManager extends AbstractSessionIdManager
/* ------------------------------------------------------------ */
/** Get the session ID with any worker ID.
*
+ * @param clusterId
* @param request
* @return sessionId plus any worker ID.
*/
@@ -66,7 +67,7 @@ public class HashSessionIdManager extends AbstractSessionIdManager
/* ------------------------------------------------------------ */
/** Get the session ID without any worker ID.
*
- * @param request
+ * @param nodeId the node id
* @return sessionId without any worker ID.
*/
public String getClusterId(String nodeId)
@@ -94,8 +95,8 @@ public class HashSessionIdManager extends AbstractSessionIdManager
}
/* ------------------------------------------------------------ */
- /*
- * @see org.eclipse.jetty.server.server.SessionManager.MetaManager#idInUse(java.lang.String)
+ /**
+ * @see SessionIdManager#idInUse(String)
*/
public boolean idInUse(String id)
{
@@ -103,8 +104,8 @@ public class HashSessionIdManager extends AbstractSessionIdManager
}
/* ------------------------------------------------------------ */
- /*
- * @see org.eclipse.jetty.server.server.SessionManager.MetaManager#addSession(javax.servlet.http.HttpSession)
+ /**
+ * @see SessionIdManager#addSession(HttpSession)
*/
public void addSession(HttpSession session)
{
@@ -112,8 +113,8 @@ public class HashSessionIdManager extends AbstractSessionIdManager
}
/* ------------------------------------------------------------ */
- /*
- * @see org.eclipse.jetty.server.server.SessionManager.MetaManager#addSession(javax.servlet.http.HttpSession)
+ /**
+ * @see SessionIdManager#removeSession(HttpSession)
*/
public void removeSession(HttpSession session)
{
@@ -121,8 +122,8 @@ public class HashSessionIdManager extends AbstractSessionIdManager
}
/* ------------------------------------------------------------ */
- /*
- * @see org.eclipse.jetty.server.server.SessionManager.MetaManager#invalidateAll(java.lang.String)
+ /**
+ * @see SessionIdManager#invalidateAll(String)
*/
public void invalidateAll(String id)
{
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 50633acbc4..5452362a4d 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
@@ -112,7 +112,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
* depending on the way the db stores identifiers.
*
* @param identifier
- * @return
+ * @return the converted identifier
*/
public String convertIdentifier (String identifier)
{
@@ -387,8 +387,6 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
*
* Makes necessary database tables and starts a Session
* scavenger thread.
- *
- * @see org.eclipse.jetty.server.session.AbstractSessionIdManager#doStart()
*/
@Override
public void doStart()
@@ -410,8 +408,6 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
/**
* Stop the scavenger.
- *
- * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
*/
@Override
public void doStop ()
@@ -431,7 +427,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
/**
* Get a connection from the driver or datasource.
*
- * @return
+ * @return the connection for the datasource
* @throws SQLException
*/
protected Connection getConnection ()
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 0ddfd131d8..ecb226fe9b 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
@@ -52,15 +52,15 @@ import org.eclipse.jetty.util.log.Log;
* contextPath (of the context owning the session)
* sessionId (unique in a context)
* lastNode (name of node last handled session)
- * accessTime (time in ms session was accessed)
- * lastAccessTime (previous time in ms session was accessed)
- * createTime (time in ms session created)
- * cookieTime (time in ms session cookie created)
- * lastSavedTime (last time in ms session access times were saved)
- * expiryTime (time in ms that the session is due to expire)
+ * accessTime (time in milliseconds session was accessed)
+ * lastAccessTime (previous time in milliseconds session was accessed)
+ * createTime (time in milliseconds session created)
+ * cookieTime (time in milliseconds session cookie created)
+ * lastSavedTime (last time in milliseconds session access times were saved)
+ * expiryTime (time in milliseconds that the session is due to expire)
* map (attribute map)
*
- * As an optimisation, to prevent thrashing the database, we do not persist
+ * As an optimization, to prevent thrashing the database, we do not persist
* the accessTime and lastAccessTime every time the session is accessed. Rather,
* we write it out every so often. The frequency is controlled by the saveIntervalSec
* field.
@@ -274,7 +274,7 @@ public class JDBCSessionManager extends AbstractSessionManager
/**
* Session restored in database.
- * @param row
+ * @param data
*/
protected Session (SessionData data)
{
@@ -442,7 +442,7 @@ public class JDBCSessionManager extends AbstractSessionManager
* This could be used eg with a JMS backplane to notify nodes
* that the session has changed and to delete the session from
* the node's cache, and re-read it from the database.
- * @param idInCluster
+ * @param session
*/
public void cacheInvalidate (Session session)
{
@@ -540,8 +540,6 @@ public class JDBCSessionManager extends AbstractSessionManager
/**
* Get all the sessions as a map of id to Session.
- *
- * @see org.eclipse.jetty.server.session.AbstractSessionManager#getSessionMap()
*/
@Override
public Map getSessionMap()
@@ -817,7 +815,7 @@ public class JDBCSessionManager extends AbstractSessionManager
/**
* Load a session from the database
* @param id
- * @return
+ * @return the session data that was loaded
* @throws Exception
*/
protected SessionData loadSession (String id, String canonicalContextPath, String vhost)
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 746a2999d8..0272e8c11f 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
@@ -35,9 +35,6 @@ import org.eclipse.jetty.util.log.Log;
/* ------------------------------------------------------------ */
/** SessionHandler.
- *
- *
- *
*/
public class SessionHandler extends ScopedHandler
{
@@ -224,8 +221,7 @@ public class SessionHandler extends ScopedHandler
throws IOException, ServletException
{
// start manual inline of nextHandle(target,baseRequest,request,response);
- //noinspection ConstantIfStatement
- if (false)
+ if (never())
nextHandle(target,baseRequest,request,response);
else if (_nextScope!=null && _nextScope==_handler)
_nextScope.doHandle(target,baseRequest,request, response);
@@ -236,8 +232,8 @@ public class SessionHandler extends ScopedHandler
/* ------------------------------------------------------------ */
/** Look for a requested session ID in cookies and URI parameters
+ * @param baseRequest
* @param request
- * @param dispatch
*/
protected void setRequestedId(Request baseRequest, HttpServletRequest request)
{
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java
index 94803ab856..25b1ac7dda 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslCertificates.java
@@ -10,9 +10,9 @@ import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.http.HttpSchemes;
-import org.eclipse.jetty.http.ssl.SslSelectChannelEndPoint;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.bio.SocketEndPoint;
+import org.eclipse.jetty.io.nio.SslSelectChannelEndPoint;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java
index f40159f08a..71bb96de93 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSelectChannelConnector.java
@@ -13,14 +13,12 @@
package org.eclipse.jetty.server.ssl;
-import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.security.KeyStore;
import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -29,7 +27,6 @@ import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLPeerUnverifiedException;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.TrustManager;
@@ -38,7 +35,6 @@ import javax.net.ssl.TrustManagerFactory;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.http.security.Password;
-import org.eclipse.jetty.http.ssl.SslSelectChannelEndPoint;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection;
@@ -47,11 +43,11 @@ import org.eclipse.jetty.io.ThreadLocalBuffers;
import org.eclipse.jetty.io.bio.SocketEndPoint;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
+import org.eclipse.jetty.io.nio.SslSelectChannelEndPoint;
import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
-import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.resource.Resource;
@@ -471,7 +467,6 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
/* ------------------------------------------------------------ */
/**
- * @throws Exception
* @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext)
*/
public SSLContext getSslContext()
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSocketConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSocketConnector.java
index 0d7fb53bff..ca99861cd9 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSocketConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ssl/SslSocketConnector.java
@@ -137,7 +137,7 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
Socket socket = _serverSocket.accept();
configure(socket);
- ConnectorEndPoint connection=new SslConnection(socket);
+ ConnectorEndPoint connection=new SslConnectorEndPoint(socket);
connection.dispatch();
}
@@ -205,14 +205,10 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
try
{
if (keystorePath!=null)
- {
keystoreInputStream = Resource.newResource(keystorePath).getInputStream();
- keystore=KeyStore.getInstance(keystoreType);
- keystore.load(keystoreInputStream,keystorePassword==null?null:keystorePassword.toString().toCharArray());
- return keystore;
- }
-
- return null;
+ keystore=KeyStore.getInstance(keystoreType);
+ keystore.load(keystoreInputStream,keystorePassword==null?null:keystorePassword.toString().toCharArray());
+ return keystore;
}
finally
{
@@ -363,13 +359,13 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
/* ------------------------------------------------------------ */
/**
- * @param addr The {@link SocketAddress address} that this server should listen on
+ * @param host The host name that this server should listen on
+ * @param port the port that this server should listen on
* @param backlog See {@link ServerSocket#bind(java.net.SocketAddress, int)}
* @return A new {@link ServerSocket socket object} bound to the supplied address with all other
* settings as per the current configuration of this connector.
- * @see #setWantClientAuth
- * @see #setNeedClientAuth
- * @see #setCipherSuites
+ * @see #setWantClientAuth(boolean)
+ * @see #setNeedClientAuth(boolean)
* @exception IOException
*/
@@ -411,10 +407,10 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
excludedCSList = new ArrayList<String>();
}
String[] enabledCipherSuites = socket.getEnabledCipherSuites();
- List<String> enabledCSList=Arrays.asList(enabledCipherSuites);
+ List<String> enabledCSList = new ArrayList<String>(Arrays.asList(enabledCipherSuites));
String[] supportedCipherSuites = socket.getSupportedCipherSuites();
- List<String> supportedCSList=Arrays.asList(supportedCipherSuites);
+ List<String> supportedCSList = Arrays.asList(supportedCipherSuites);
for (String cipherName : includedCSList)
{
@@ -432,7 +428,7 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
enabledCSList.remove(cipherName);
}
}
- enabledCipherSuites=enabledCSList.toArray(new String[0]);
+ enabledCipherSuites = enabledCSList.toArray(new String[enabledCSList.size()]);
socket.setEnabledCipherSuites(enabledCipherSuites);
}
@@ -557,7 +553,6 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
/* ------------------------------------------------------------ */
/**
- * @throws Exception
* @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext)
*/
public SSLContext getSslContext()
@@ -577,10 +572,10 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
/* ------------------------------------------------------------ */
/**
- * Set the value of the _wantClientAuth property. This property is used when
- * {@link #newServerSocket(SocketAddress, int) opening server sockets}.
+ * Set the value of the _wantClientAuth property. This property is used
+ * internally when opening server sockets.
*
- * @param wantClientAuth true iff we want client certificate authentication.
+ * @param wantClientAuth true if we want client certificate authentication.
* @see SSLServerSocket#setWantClientAuth
*/
public void setWantClientAuth(boolean wantClientAuth)
@@ -607,14 +602,19 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
}
/* ------------------------------------------------------------ */
- public class SslConnection extends ConnectorEndPoint
+ public class SslConnectorEndPoint extends ConnectorEndPoint
{
- public SslConnection(Socket socket) throws IOException
+ public SslConnectorEndPoint(Socket socket) throws IOException
{
super(socket);
}
@Override
+ public void shutdownOutput() throws IOException
+ {
+ }
+
+ @Override
public void run()
{
try
@@ -667,7 +667,8 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
/* ------------------------------------------------------------ */
/**
* Unsupported.
- * @see org.eclipse.jetty.server.ssl.SslConnector#getAlgorithm()
+ *
+ * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past)
*/
public String getAlgorithm()
{
@@ -677,7 +678,8 @@ public class SslSocketConnector extends SocketConnector implements SslConnector
/* ------------------------------------------------------------ */
/**
* Unsupported.
- * @see org.eclipse.jetty.server.ssl.SslConnector#setAlgorithm(java.lang.String)
+ *
+ * TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past)
*/
public void setAlgorithm(String algorithm)
{

Back to the top