The ability to intercept callbacks (see {@link #setEventListener(HttpEventListener)}
*
*
- *
The HttpExchange class is intended to be used by a developer wishing to have close asynchronous
- * interaction with the the exchange.
- * Typically a developer will extend the HttpExchange class with a derived
- * class that overrides some or all of the onXxx callbacks.
- * There are also some predefined HttpExchange subtypes that can be used as a basis,
- * see {@link org.eclipse.jetty.client.ContentExchange} and {@link org.eclipse.jetty.client.CachedExchange}.
+ *
+ * The HttpExchange class is intended to be used by a developer wishing to have close asynchronous interaction with the the exchange.
+ * Typically a developer will extend the HttpExchange class with a derived class that overrides some or all of the onXxx callbacks.
+ * There are also some predefined HttpExchange subtypes that can be used as a basis, see {@link org.eclipse.jetty.client.ContentExchange} and
+ * {@link org.eclipse.jetty.client.CachedExchange}.
+ *
*
- *
Typically the HttpExchange is passed to the {@link HttpClient#send(HttpExchange)} method, which in
- * turn selects a {@link HttpDestination} and calls its {@link HttpDestination#send(HttpExchange)}, which
- * then creates or selects a {@link HttpConnection} and calls its {@link HttpConnection#send(HttpExchange)}.
- * A developer may wish to directly call send on the destination or connection if they wish to bypass
- * some handling provided (eg Cookie handling in the HttpDestination).
+ *
+ * Typically the HttpExchange is passed to the {@link HttpClient#send(HttpExchange)} method, which in turn selects a {@link HttpDestination} and calls its
+ * {@link HttpDestination#send(HttpExchange)}, which then creates or selects a {@link HttpConnection} and calls its {@link HttpConnection#send(HttpExchange)}. A
+ * developer may wish to directly call send on the destination or connection if they wish to bypass some handling provided (eg Cookie handling in the
+ * HttpDestination).
+ *
*
- *
In some circumstances, the HttpClient or HttpDestination may wish to retry a HttpExchange (eg. failed
- * pipeline request, authentication retry or redirection). In such cases, the HttpClient and/or HttpDestination
- * may insert their own HttpExchangeListener to intercept and filter the call backs intended for the
- * HttpExchange.
+ *
+ * In some circumstances, the HttpClient or HttpDestination may wish to retry a HttpExchange (eg. failed pipeline request, authentication retry or redirection).
+ * In such cases, the HttpClient and/or HttpDestination may insert their own HttpExchangeListener to intercept and filter the call backs intended for the
+ * HttpExchange.
+ *
*/
public class HttpExchange
{
@@ -106,9 +110,10 @@ public class HttpExchange
// a timeout for this exchange
private long _timeout = -1;
private volatile Timeout.Task _timeoutTask;
-
- private long _lastStateChange=-1;
+ private long _lastStateChange=System.currentTimeMillis();
private long _sent=-1;
+ private int _lastState=-1;
+ private int _lastStatePeriod=-1;
boolean _onRequestCompleteDone;
boolean _onResponseCompleteDone;
@@ -131,8 +136,10 @@ public class HttpExchange
}
/**
- * @param status the status to wait for
- * @throws InterruptedException if the waiting thread is interrupted
+ * @param status
+ * the status to wait for
+ * @throws InterruptedException
+ * if the waiting thread is interrupted
* @deprecated Use {@link #waitForDone()} instead
*/
@Deprecated
@@ -142,21 +149,17 @@ public class HttpExchange
}
/**
- * Wait until the exchange is "done".
- * Done is defined as when a final state has been passed to the
- * HttpExchange via the associated onXxx call. Note that an
- * exchange can transit a final state when being used as part
- * of a dialog (eg {@link SecurityListener}. Done status
- * is thus defined as:
- * done == onConnectionFailed
- * || onException
- * || onExpire
- * || onRequestComplete && onResponseComplete
+ * Wait until the exchange is "done". Done is defined as when a final state has been passed to the HttpExchange via the associated onXxx call. Note that an
+ * exchange can transit a final state when being used as part of a dialog (eg {@link SecurityListener}. Done status is thus defined as:
+ *
+ *
+ *
* @return the done status
* @throws InterruptedException
*/
- public int waitForDone () throws InterruptedException
+ public int waitForDone() throws InterruptedException
{
synchronized (this)
{
@@ -170,12 +173,12 @@ public class HttpExchange
{
// TODO - this should do a cancel and wakeup everybody that was waiting.
// might need a version number concept
- synchronized(this)
+ synchronized (this)
{
- _timeoutTask=null;
- _onRequestCompleteDone=false;
- _onResponseCompleteDone=false;
- _onDone=false;
+ _timeoutTask = null;
+ _onRequestCompleteDone = false;
+ _onResponseCompleteDone = false;
+ _onDone = false;
setStatus(STATUS_START);
}
}
@@ -186,13 +189,16 @@ public class HttpExchange
{
int oldStatus = _status.get();
boolean set = false;
- if (oldStatus!=newStatus)
+ if (oldStatus != newStatus)
{
- _lastStateChange=System.currentTimeMillis();
+ long now = System.currentTimeMillis();
+ _lastStatePeriod=(int)(now-_lastStateChange);
+ _lastState=oldStatus;
+ _lastStateChange=now;
if (newStatus==STATUS_SENDING_REQUEST)
_sent=_lastStateChange;
}
-
+
// State machine: from which old status you can go into which new status
switch (oldStatus)
{
@@ -204,7 +210,10 @@ public class HttpExchange
case STATUS_WAITING_FOR_COMMIT:
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
- set=_status.compareAndSet(oldStatus,newStatus);
+ set = _status.compareAndSet(oldStatus,newStatus);
+ break;
+ case STATUS_EXPIRED:
+ set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@@ -214,11 +223,10 @@ public class HttpExchange
case STATUS_WAITING_FOR_COMMIT:
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
- set=_status.compareAndSet(oldStatus,newStatus);
+ set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
- if (set=_status.compareAndSet(oldStatus,newStatus))
- getEventListener().onExpire();
+ set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@@ -228,11 +236,10 @@ public class HttpExchange
case STATUS_SENDING_REQUEST:
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
- set=_status.compareAndSet(oldStatus,newStatus);
+ set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
- if (set=_status.compareAndSet(oldStatus,newStatus))
- getEventListener().onExpire();
+ set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@@ -240,16 +247,15 @@ public class HttpExchange
switch (newStatus)
{
case STATUS_WAITING_FOR_RESPONSE:
- if (set=_status.compareAndSet(oldStatus,newStatus))
+ if (set = _status.compareAndSet(oldStatus,newStatus))
getEventListener().onRequestCommitted();
break;
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
- set=_status.compareAndSet(oldStatus,newStatus);
+ set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
- if (set=_status.compareAndSet(oldStatus,newStatus))
- getEventListener().onExpire();
+ set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@@ -259,11 +265,10 @@ public class HttpExchange
case STATUS_PARSING_HEADERS:
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
- set=_status.compareAndSet(oldStatus,newStatus);
+ set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
- if (set=_status.compareAndSet(oldStatus,newStatus))
- getEventListener().onExpire();
+ set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@@ -271,16 +276,15 @@ public class HttpExchange
switch (newStatus)
{
case STATUS_PARSING_CONTENT:
- if (set=_status.compareAndSet(oldStatus,newStatus))
+ if (set = _status.compareAndSet(oldStatus,newStatus))
getEventListener().onResponseHeaderComplete();
break;
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
- set=_status.compareAndSet(oldStatus,newStatus);
+ set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
- if (set=_status.compareAndSet(oldStatus,newStatus))
- getEventListener().onExpire();
+ set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@@ -288,16 +292,15 @@ public class HttpExchange
switch (newStatus)
{
case STATUS_COMPLETED:
- if (set=_status.compareAndSet(oldStatus,newStatus))
+ if (set = _status.compareAndSet(oldStatus,newStatus))
getEventListener().onResponseComplete();
break;
case STATUS_CANCELLING:
case STATUS_EXCEPTED:
- set=_status.compareAndSet(oldStatus,newStatus);
+ set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_EXPIRED:
- if (set=_status.compareAndSet(oldStatus,newStatus))
- getEventListener().onExpire();
+ set = setStatusExpired(newStatus,oldStatus);
break;
}
break;
@@ -307,12 +310,12 @@ public class HttpExchange
case STATUS_START:
case STATUS_EXCEPTED:
case STATUS_WAITING_FOR_RESPONSE:
- set=_status.compareAndSet(oldStatus,newStatus);
+ set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_CANCELLING:
case STATUS_EXPIRED:
// Don't change the status, it's too late
- set=true;
+ set = true;
break;
}
break;
@@ -321,12 +324,12 @@ public class HttpExchange
{
case STATUS_EXCEPTED:
case STATUS_CANCELLED:
- if (set=_status.compareAndSet(oldStatus,newStatus))
+ if (set = _status.compareAndSet(oldStatus,newStatus))
done();
break;
default:
// Ignore other statuses, we're cancelling
- set=true;
+ set = true;
break;
}
break;
@@ -336,10 +339,10 @@ public class HttpExchange
switch (newStatus)
{
case STATUS_START:
- set=_status.compareAndSet(oldStatus,newStatus);
+ set = _status.compareAndSet(oldStatus,newStatus);
break;
default:
- set=true;
+ set = true;
break;
}
break;
@@ -357,6 +360,14 @@ public class HttpExchange
}
}
+ private boolean setStatusExpired(int newStatus, int oldStatus)
+ {
+ boolean set;
+ if (set = _status.compareAndSet(oldStatus,newStatus))
+ getEventListener().onExpire();
+ return set;
+ }
+
public boolean isDone()
{
synchronized (this)
@@ -369,7 +380,7 @@ public class HttpExchange
* @deprecated
*/
@Deprecated
- public boolean isDone (int status)
+ public boolean isDone(int status)
{
return isDone();
}
@@ -381,10 +392,10 @@ public class HttpExchange
public void setEventListener(HttpEventListener listener)
{
- _listener=listener;
+ _listener = listener;
}
- public void setTimeout( long timeout )
+ public void setTimeout(long timeout)
{
_timeout = timeout;
}
@@ -395,7 +406,8 @@ public class HttpExchange
}
/**
- * @param url an absolute URL (for example 'http://localhost/foo/bar?a=1')
+ * @param url
+ * an absolute URL (for example 'http://localhost/foo/bar?a=1')
*/
public void setURL(String url)
{
@@ -403,7 +415,8 @@ public class HttpExchange
}
/**
- * @param address the address of the server
+ * @param address
+ * the address of the server
*/
public void setAddress(Address address)
{
@@ -421,8 +434,7 @@ public class HttpExchange
/**
* the local address used by the connection
*
- * Note: this method will not be populated unless the exchange
- * has been executed by the HttpClient
+ * Note: this method will not be populated unless the exchange has been executed by the HttpClient
*
* @return the local address used for the running of the exchange if available, null otherwise.
*/
@@ -432,15 +444,17 @@ public class HttpExchange
}
/**
- * @param scheme the scheme of the URL (for example 'http')
+ * @param scheme
+ * the scheme of the URL (for example 'http')
*/
public void setScheme(Buffer scheme)
{
_scheme = scheme;
}
-
+
/**
- * @param scheme the scheme of the URL (for example 'http')
+ * @param scheme
+ * the scheme of the URL (for example 'http')
*/
public void setScheme(String scheme)
{
@@ -464,7 +478,8 @@ public class HttpExchange
}
/**
- * @param version the HTTP protocol version as integer, 9, 10 or 11 for 0.9, 1.0 or 1.1
+ * @param version
+ * the HTTP protocol version as integer, 9, 10 or 11 for 0.9, 1.0 or 1.1
*/
public void setVersion(int version)
{
@@ -472,7 +487,8 @@ public class HttpExchange
}
/**
- * @param version the HTTP protocol version as string
+ * @param version
+ * the HTTP protocol version as string
*/
public void setVersion(String version)
{
@@ -493,7 +509,8 @@ public class HttpExchange
}
/**
- * @param method the HTTP method (for example 'GET')
+ * @param method
+ * the HTTP method (for example 'GET')
*/
public void setMethod(String method)
{
@@ -528,9 +545,10 @@ public class HttpExchange
}
/**
- * Set the request URI
+ * Set the request URI
*
- * @param uri new request URI
+ * @param uri
+ * new request URI
* @see #setRequestURI(String)
* @deprecated
*/
@@ -541,36 +559,41 @@ public class HttpExchange
}
/**
- * Set the request URI
+ * Set the request URI
*
* Per RFC 2616 sec5, Request-URI = "*" | absoluteURI | abs_path | authority
- * where:
- * "*" - request applies to server itself
+ * where:
+ *
+ * "*" - request applies to server itself
* absoluteURI - required for proxy requests, e.g. http://localhost:8080/context
- * (this form is generated automatically by HttpClient)
- * abs_path - used for most methods, e.g. /context
- * authority - used for CONNECT method only, e.g. localhost:8080
+ * (this form is generated automatically by HttpClient)
+ * abs_path - used for most methods, e.g. /context
+ * authority - used for CONNECT method only, e.g. localhost:8080
*
* For complete definition of URI components, see RFC 2396 sec3.
- *
- * @param uri new request URI
+ *
+ * @param uri
+ * new request URI
*/
public void setRequestURI(String uri)
{
_uri = uri;
}
-
+
/* ------------------------------------------------------------ */
/**
- * @param uri an absolute URI (for example 'http://localhost/foo/bar?a=1')
+ * @param uri
+ * an absolute URI (for example 'http://localhost/foo/bar?a=1')
*/
public void setURI(URI uri)
{
if (!uri.isAbsolute())
- throw new IllegalArgumentException("!Absolute URI: "+uri);
-
+ throw new IllegalArgumentException("!Absolute URI: " + uri);
+
if (uri.isOpaque())
- throw new IllegalArgumentException("Opaque URI: "+uri);
+ throw new IllegalArgumentException("Opaque URI: " + uri);
+
+ LOG.debug("URI = {}",uri.toASCIIString());
String scheme = uri.getScheme();
int port = uri.getPort();
@@ -582,13 +605,16 @@ public class HttpExchange
HttpURI httpUri = new HttpURI(uri);
String completePath = httpUri.getCompletePath();
- setRequestURI(completePath==null ? "/" : completePath);
+ setRequestURI(completePath == null?"/":completePath);
}
/**
* Adds the specified request header
- * @param name the header name
- * @param value the header value
+ *
+ * @param name
+ * the header name
+ * @param value
+ * the header value
*/
public void addRequestHeader(String name, String value)
{
@@ -597,8 +623,11 @@ public class HttpExchange
/**
* Adds the specified request header
- * @param name the header name
- * @param value the header value
+ *
+ * @param name
+ * the header name
+ * @param value
+ * the header value
*/
public void addRequestHeader(Buffer name, Buffer value)
{
@@ -607,30 +636,37 @@ public class HttpExchange
/**
* Sets the specified request header
- * @param name the header name
- * @param value the header value
+ *
+ * @param name
+ * the header name
+ * @param value
+ * the header value
*/
public void setRequestHeader(String name, String value)
{
- getRequestFields().put(name, value);
+ getRequestFields().put(name,value);
}
/**
* Sets the specified request header
- * @param name the header name
- * @param value the header value
+ *
+ * @param name
+ * the header name
+ * @param value
+ * the header value
*/
public void setRequestHeader(Buffer name, Buffer value)
{
- getRequestFields().put(name, value);
+ getRequestFields().put(name,value);
}
/**
- * @param value the content type of the request
+ * @param value
+ * the content type of the request
*/
public void setRequestContentType(String value)
{
- getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER, value);
+ getRequestFields().put(HttpHeaders.CONTENT_TYPE_BUFFER,value);
}
/**
@@ -642,7 +678,8 @@ public class HttpExchange
}
/**
- * @param requestContent the request content
+ * @param requestContent
+ * the request content
*/
public void setRequestContent(Buffer requestContent)
{
@@ -650,7 +687,8 @@ public class HttpExchange
}
/**
- * @param stream the request content as a stream
+ * @param stream
+ * the request content as a stream
*/
public void setRequestContentSource(InputStream stream)
{
@@ -708,7 +746,8 @@ public class HttpExchange
}
/**
- * @param retryStatus whether a retry will be attempted or not
+ * @param retryStatus
+ * whether a retry will be attempted or not
*/
public void setRetryStatus(boolean retryStatus)
{
@@ -716,13 +755,10 @@ public class HttpExchange
}
/**
- * Initiates the cancelling of this exchange.
- * The status of the exchange is set to {@link #STATUS_CANCELLING}.
- * Cancelling the exchange is an asynchronous operation with respect to the request/response,
- * and as such checking the request/response status of a cancelled exchange may return undefined results
- * (for example it may have only some of the response headers being sent by the server).
- * The cancelling of the exchange is completed when the exchange status (see {@link #getStatus()}) is
- * {@link #STATUS_CANCELLED}, and this can be waited using {@link #waitForDone()}.
+ * Initiates the cancelling of this exchange. The status of the exchange is set to {@link #STATUS_CANCELLING}. Cancelling the exchange is an asynchronous
+ * operation with respect to the request/response, and as such checking the request/response status of a cancelled exchange may return undefined results
+ * (for example it may have only some of the response headers being sent by the server). The cancelling of the exchange is completed when the exchange
+ * status (see {@link #getStatus()}) is {@link #STATUS_CANCELLED}, and this can be waited using {@link #waitForDone()}.
*/
public void cancel()
{
@@ -732,10 +768,10 @@ public class HttpExchange
private void done()
{
- synchronized(this)
+ synchronized (this)
{
disassociate();
- _onDone=true;
+ _onDone = true;
notifyAll();
}
}
@@ -764,8 +800,8 @@ public class HttpExchange
void associate(HttpConnection connection)
{
- if (connection.getEndPoint().getLocalHost() != null)
- _localAddress = new Address(connection.getEndPoint().getLocalHost(), connection.getEndPoint().getLocalPort());
+ if (connection.getEndPoint().getLocalHost() != null)
+ _localAddress = new Address(connection.getEndPoint().getLocalHost(),connection.getEndPoint().getLocalPort());
_connection = connection;
if (getStatus() == STATUS_CANCELLING)
@@ -789,33 +825,60 @@ public class HttpExchange
public static String toState(int s)
{
String state;
- switch(s)
+ switch (s)
{
- case STATUS_START: state="START"; break;
- case STATUS_WAITING_FOR_CONNECTION: state="CONNECTING"; break;
- case STATUS_WAITING_FOR_COMMIT: state="CONNECTED"; break;
- case STATUS_SENDING_REQUEST: state="SENDING"; break;
- case STATUS_WAITING_FOR_RESPONSE: state="WAITING"; break;
- case STATUS_PARSING_HEADERS: state="HEADERS"; break;
- case STATUS_PARSING_CONTENT: state="CONTENT"; break;
- case STATUS_COMPLETED: state="COMPLETED"; break;
- case STATUS_EXPIRED: state="EXPIRED"; break;
- case STATUS_EXCEPTED: state="EXCEPTED"; break;
- case STATUS_CANCELLING: state="CANCELLING"; break;
- case STATUS_CANCELLED: state="CANCELLED"; break;
- default: state="UNKNOWN";
+ case STATUS_START:
+ state = "START";
+ break;
+ case STATUS_WAITING_FOR_CONNECTION:
+ state = "CONNECTING";
+ break;
+ case STATUS_WAITING_FOR_COMMIT:
+ state = "CONNECTED";
+ break;
+ case STATUS_SENDING_REQUEST:
+ state = "SENDING";
+ break;
+ case STATUS_WAITING_FOR_RESPONSE:
+ state = "WAITING";
+ break;
+ case STATUS_PARSING_HEADERS:
+ state = "HEADERS";
+ break;
+ case STATUS_PARSING_CONTENT:
+ state = "CONTENT";
+ break;
+ case STATUS_COMPLETED:
+ state = "COMPLETED";
+ break;
+ case STATUS_EXPIRED:
+ state = "EXPIRED";
+ break;
+ case STATUS_EXCEPTED:
+ state = "EXCEPTED";
+ break;
+ case STATUS_CANCELLING:
+ state = "CANCELLING";
+ break;
+ case STATUS_CANCELLED:
+ state = "CANCELLED";
+ break;
+ default:
+ state = "UNKNOWN";
}
return state;
}
-
+
@Override
public String toString()
{
String state=toState(getStatus());
long now=System.currentTimeMillis();
long forMs = now -_lastStateChange;
- String s= String.format("%s@%x=%s//%s%s#%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,state,forMs);
- if (getStatus()>=STATUS_SENDING_REQUEST)
+ String s= _lastState>=0
+ ?String.format("%s@%x=%s//%s%s#%s(%dms)->%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,toState(_lastState),_lastStatePeriod,state,forMs)
+ :String.format("%s@%x=%s//%s%s#%s(%dms)",getClass().getSimpleName(),hashCode(),_method,_address,_uri,state,forMs);
+ if (getStatus()>=STATUS_SENDING_REQUEST && _sent>0)
s+="sent="+(now-_sent)+"ms";
return s;
}
@@ -828,79 +891,93 @@ public class HttpExchange
}
/**
- * Callback called when the request headers have been sent to the server.
- * This implementation does nothing.
- * @throws IOException allowed to be thrown by overriding code
+ * Callback called when the request headers have been sent to the server. This implementation does nothing.
+ *
+ * @throws IOException
+ * allowed to be thrown by overriding code
*/
protected void onRequestCommitted() throws IOException
{
}
/**
- * Callback called when the request and its body have been sent to the server.
- * This implementation does nothing.
- * @throws IOException allowed to be thrown by overriding code
+ * Callback called when the request and its body have been sent to the server. This implementation does nothing.
+ *
+ * @throws IOException
+ * allowed to be thrown by overriding code
*/
protected void onRequestComplete() throws IOException
{
}
/**
- * Callback called when a response status line has been received from the server.
- * This implementation does nothing.
- * @param version the HTTP version
- * @param status the HTTP status code
- * @param reason the HTTP status reason string
- * @throws IOException allowed to be thrown by overriding code
+ * Callback called when a response status line has been received from the server. This implementation does nothing.
+ *
+ * @param version
+ * the HTTP version
+ * @param status
+ * the HTTP status code
+ * @param reason
+ * the HTTP status reason string
+ * @throws IOException
+ * allowed to be thrown by overriding code
*/
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
}
/**
- * Callback called for each response header received from the server.
- * This implementation does nothing.
- * @param name the header name
- * @param value the header value
- * @throws IOException allowed to be thrown by overriding code
+ * Callback called for each response header received from the server. This implementation does nothing.
+ *
+ * @param name
+ * the header name
+ * @param value
+ * the header value
+ * @throws IOException
+ * allowed to be thrown by overriding code
*/
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
}
/**
- * Callback called when the response headers have been completely received from the server.
- * This implementation does nothing.
- * @throws IOException allowed to be thrown by overriding code
+ * Callback called when the response headers have been completely received from the server. This implementation does nothing.
+ *
+ * @throws IOException
+ * allowed to be thrown by overriding code
*/
protected void onResponseHeaderComplete() throws IOException
{
}
/**
- * Callback called for each chunk of the response content received from the server.
- * This implementation does nothing.
- * @param content the buffer holding the content chunk
- * @throws IOException allowed to be thrown by overriding code
+ * Callback called for each chunk of the response content received from the server. This implementation does nothing.
+ *
+ * @param content
+ * the buffer holding the content chunk
+ * @throws IOException
+ * allowed to be thrown by overriding code
*/
protected void onResponseContent(Buffer content) throws IOException
{
}
/**
- * Callback called when the entire response has been received from the server
- * This implementation does nothing.
- * @throws IOException allowed to be thrown by overriding code
+ * Callback called when the entire response has been received from the server This implementation does nothing.
+ *
+ * @throws IOException
+ * allowed to be thrown by overriding code
*/
protected void onResponseComplete() throws IOException
{
}
/**
- * Callback called when an exception was thrown during an attempt to establish the connection
- * with the server (for example the server is not listening).
+ * Callback called when an exception was thrown during an attempt to establish the connection with the server (for example the server is not listening).
* This implementation logs a warning.
- * @param x the exception thrown attempting to establish the connection with the server
+ *
+ * @param x
+ * the exception thrown attempting to establish the connection with the server
*/
protected void onConnectionFailed(Throwable x)
{
@@ -908,9 +985,10 @@ public class HttpExchange
}
/**
- * Callback called when any other exception occurs during the handling of this exchange.
- * This implementation logs a warning.
- * @param x the exception thrown during the handling of this exchange
+ * Callback called when any other exception occurs during the handling of this exchange. This implementation logs a warning.
+ *
+ * @param x
+ * the exception thrown during the handling of this exchange
*/
protected void onException(Throwable x)
{
@@ -918,8 +996,7 @@ public class HttpExchange
}
/**
- * Callback called when no response has been received within the timeout.
- * This implementation logs a warning.
+ * Callback called when no response has been received within the timeout. This implementation logs a warning.
*/
protected void onExpire()
{
@@ -927,9 +1004,10 @@ public class HttpExchange
}
/**
- * Callback called when the request is retried (due to failures or authentication).
- * Implementations must reset any consumable content that needs to be sent.
- * @throws IOException allowed to be thrown by overriding code
+ * Callback called when the request is retried (due to failures or authentication). Implementations must reset any consumable content that needs to be sent.
+ *
+ * @throws IOException
+ * allowed to be thrown by overriding code
*/
protected void onRetry() throws IOException
{
@@ -948,8 +1026,7 @@ public class HttpExchange
}
/**
- * @return true if the exchange should have listeners configured for it by the destination,
- * false if this is being managed elsewhere
+ * @return true if the exchange should have listeners configured for it by the destination, false if this is being managed elsewhere
* @see #setConfigureListeners(boolean)
*/
public boolean configureListeners()
@@ -958,7 +1035,8 @@ public class HttpExchange
}
/**
- * @param autoConfigure whether the listeners are configured by the destination or elsewhere
+ * @param autoConfigure
+ * whether the listeners are configured by the destination or elsewhere
*/
public void setConfigureListeners(boolean autoConfigure)
{
@@ -981,7 +1059,7 @@ public class HttpExchange
HttpClient httpClient = destination.getHttpClient();
long timeout = getTimeout();
if (timeout > 0)
- httpClient.schedule(_timeoutTask, timeout);
+ httpClient.schedule(_timeoutTask,timeout);
else
httpClient.schedule(_timeoutTask);
}
@@ -1045,7 +1123,7 @@ public class HttpExchange
}
finally
{
- synchronized(HttpExchange.this)
+ synchronized (HttpExchange.this)
{
_onRequestCompleteDone = true;
// Member _onDone may already be true, for example
@@ -1066,7 +1144,7 @@ public class HttpExchange
}
finally
{
- synchronized(HttpExchange.this)
+ synchronized (HttpExchange.this)
{
_onResponseCompleteDone = true;
// Member _onDone may already be true, for example
@@ -1101,7 +1179,7 @@ public class HttpExchange
public void onRetry()
{
- HttpExchange.this.setRetryStatus( true );
+ HttpExchange.this.setRetryStatus(true);
try
{
HttpExchange.this.onRetry();
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/RedirectListener.java b/jetty-client/src/main/java/org/eclipse/jetty/client/RedirectListener.java
index b46d2bcc4fa..00bc4595432 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/RedirectListener.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/RedirectListener.java
@@ -110,25 +110,49 @@ public class RedirectListener extends HttpEventListenerWrapper
if (_location != null)
{
if (_location.indexOf("://")>0)
+ {
_exchange.setURL(_location);
+ }
else
+ {
_exchange.setRequestURI(_location);
+ }
// destination may have changed
- HttpDestination destination=_destination.getHttpClient().getDestination(_exchange.getAddress(),HttpSchemes.HTTPS.equals(String.valueOf(_exchange.getScheme())));
-
+ boolean isHttps = HttpSchemes.HTTPS.equals(String.valueOf(_exchange.getScheme()));
+ HttpDestination destination=_destination.getHttpClient().getDestination(_exchange.getAddress(),isHttps);
+
if (_destination==destination)
+ {
_destination.resend(_exchange);
+ }
else
{
// unwrap to find ultimate listener.
HttpEventListener listener=this;
while(listener instanceof HttpEventListenerWrapper)
+ {
listener=((HttpEventListenerWrapper)listener).getEventListener();
+ }
+
//reset the listener
_exchange.getEventListener().onRetry();
_exchange.reset();
_exchange.setEventListener(listener);
+
+ // Set the new Host header
+ Address address = _exchange.getAddress();
+ int port = address.getPort();
+ StringBuilder hostHeader = new StringBuilder( 64 );
+ hostHeader.append( address.getHost() );
+ if( !( ( port == 80 && !isHttps ) || ( port == 443 && isHttps ) ) )
+ {
+ hostHeader.append( ':' );
+ hostHeader.append( port );
+ }
+
+ _exchange.setRequestHeader( HttpHeaders.HOST, hostHeader.toString() );
+
destination.send(_exchange);
}
@@ -156,5 +180,28 @@ public class RedirectListener extends HttpEventListenerWrapper
super.onRetry();
}
-}
+ /**
+ * Delegate failed connection
+ */
+ @Override
+ public void onConnectionFailed( Throwable ex )
+ {
+ setDelegatingRequests(true);
+ setDelegatingResponses(true);
+
+ super.onConnectionFailed( ex );
+ }
+
+ /**
+ * Delegate onException
+ */
+ @Override
+ public void onException( Throwable ex )
+ {
+ setDelegatingRequests(true);
+ setDelegatingResponses(true);
+
+ super.onException( ex );
+ }
+}
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/SelectConnector.java b/jetty-client/src/main/java/org/eclipse/jetty/client/SelectConnector.java
index 333c4166ba4..fd37190a2b5 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/SelectConnector.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/SelectConnector.java
@@ -15,10 +15,13 @@ package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.SocketTimeoutException;
+import java.net.UnknownHostException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
+import java.nio.channels.UnresolvedAddressException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
@@ -48,7 +51,6 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
private final HttpClient _httpClient;
private final Manager _selectorManager=new Manager();
private final Map _connectingChannels = new ConcurrentHashMap();
- private SSLContext _sslContext;
private Buffers _sslBuffers;
/**
@@ -89,31 +91,34 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
public void startConnection( HttpDestination destination )
throws IOException
{
+ SocketChannel channel = null;
try
{
- SocketChannel channel = SocketChannel.open();
+ channel = SocketChannel.open();
Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
channel.socket().setTcpNoDelay(true);
if (_httpClient.isConnectBlocking())
{
- channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
- channel.configureBlocking(false);
- _selectorManager.register( channel, destination );
+ channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
+ channel.configureBlocking(false);
+ _selectorManager.register( channel, destination );
}
else
{
- channel.configureBlocking( false );
- channel.connect(address.toSocketAddress());
- _selectorManager.register( channel, destination );
- ConnectTimeout connectTimeout = new ConnectTimeout(channel, destination);
+ channel.configureBlocking(false);
+ channel.connect(address.toSocketAddress());
+ _selectorManager.register(channel,destination);
+ ConnectTimeout connectTimeout = new ConnectTimeout(channel,destination);
_httpClient.schedule(connectTimeout,_httpClient.getConnectTimeout());
- _connectingChannels.put(channel, connectTimeout);
+ _connectingChannels.put(channel,connectTimeout);
}
}
catch(IOException ex)
{
+ if (channel != null)
+ channel.close();
destination.onConnectionFailed(ex);
}
}
@@ -194,19 +199,16 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
private synchronized SSLEngine newSslEngine(SocketChannel channel) throws IOException
{
SslContextFactory sslContextFactory = _httpClient.getSslContextFactory();
- if (_sslContext == null)
- _sslContext = sslContextFactory.getSslContext();
-
SSLEngine sslEngine;
- if (channel != null && sslContextFactory.isSessionCachingEnabled())
+ if (channel != null)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
- sslEngine = _sslContext.createSSLEngine(peerHost, peerPort);
+ sslEngine = sslContextFactory.newSslEngine(peerHost, peerPort);
}
else
{
- sslEngine = _sslContext.createSSLEngine();
+ sslEngine = sslContextFactory.newSslEngine();
}
sslEngine.setUseClientMode(true);
sslEngine.beginHandshake();
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/SocketConnector.java b/jetty-client/src/main/java/org/eclipse/jetty/client/SocketConnector.java
index 226cd644ffd..031c0cb5bb3 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/SocketConnector.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/SocketConnector.java
@@ -45,18 +45,9 @@ class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector
public void startConnection(final HttpDestination destination) throws IOException
{
- Socket socket=null;
-
- if ( destination.isSecure() )
- {
- SSLContext sslContext = _httpClient.getSSLContext();
- socket = sslContext.getSocketFactory().createSocket();
- }
- else
- {
- LOG.debug("Using Regular Socket");
- socket = SocketFactory.getDefault().createSocket();
- }
+ Socket socket= destination.isSecure()
+ ?_httpClient.getSslContextFactory().newSslSocket()
+ :SocketFactory.getDefault().createSocket();
socket.setSoTimeout(0);
socket.setTcpNoDelay(true);
@@ -97,6 +88,17 @@ class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector
destination.onException(e);
}
}
+ finally
+ {
+ try
+ {
+ destination.returnConnection(connection,true);
+ }
+ catch (IOException e)
+ {
+ LOG.debug(e);
+ }
+ }
}
});
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpExchangeCancelTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpExchangeCancelTest.java
index cb5812780a2..c1d5c3da2c1 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpExchangeCancelTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/AbstractHttpExchangeCancelTest.java
@@ -14,9 +14,7 @@
package org.eclipse.jetty.client;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.*;
import java.io.IOException;
import java.net.SocketTimeoutException;
@@ -34,7 +32,6 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.log.StdErrLog;
import org.junit.After;
import org.junit.Before;
@@ -45,8 +42,6 @@ import org.junit.Test;
*/
public abstract class AbstractHttpExchangeCancelTest
{
- private static final Logger LOG = Log.getLogger(AbstractHttpExchangeCancelTest.class);
-
private Server server;
private Connector connector;
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSslHttpExchangeTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSslHttpExchangeTest.java
index f5ac43dc403..9cef46582f1 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSslHttpExchangeTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/AsyncSslHttpExchangeTest.java
@@ -13,19 +13,31 @@
package org.eclipse.jetty.client;
+import org.eclipse.jetty.client.helperClasses.AsyncSslServerAndClientCreator;
+import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest
{
- @Override
- public void setUp() throws Exception
+ private static ServerAndClientCreator serverAndClientCreator = new AsyncSslServerAndClientCreator();
+
+ @Before
+ public void setUpOnce() throws Exception
{
_scheme="https";
- startServer();
- _httpClient=new HttpClient();
- _httpClient.setIdleTimeout(2000);
- _httpClient.setTimeout(2500);
- _httpClient.setConnectTimeout(1000);
- _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
- _httpClient.setMaxConnectionsPerAddress(2);
- _httpClient.start();
+ _server = serverAndClientCreator.createServer();
+ _httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
+ _port = _server.getConnectors()[0].getLocalPort();
}
+
+ @Test
+ public void testPerf1() throws Exception
+ {
+ sender(10,true);
+ }
+
+
+
}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalKeyStoreAsyncSslHttpExchangeTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalKeyStoreAsyncSslHttpExchangeTest.java
index 445947e3534..27af22c21ed 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalKeyStoreAsyncSslHttpExchangeTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ExternalKeyStoreAsyncSslHttpExchangeTest.java
@@ -13,28 +13,23 @@
package org.eclipse.jetty.client;
-import java.io.FileInputStream;
-
-import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.client.helperClasses.ExternalKeyStoreAsyncSslServerAndClientCreator;
+import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
+import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
public class ExternalKeyStoreAsyncSslHttpExchangeTest extends SslHttpExchangeTest
{
- @Override
- public void setUp() throws Exception
+ private static ServerAndClientCreator serverAndClientCreator = new ExternalKeyStoreAsyncSslServerAndClientCreator();
+
+ @Before
+ public void setUpOnce() throws Exception
{
- _scheme = "https";
- startServer();
- _httpClient = new HttpClient();
- _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
- _httpClient.setMaxConnectionsPerAddress(2);
-
- String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
-
- _httpClient.setKeyStoreInputStream(new FileInputStream(keystore));
- _httpClient.setKeyStorePassword("storepwd");
- _httpClient.setKeyManagerPassword("keypwd");
- _httpClient.start();
+ _scheme="https";
+ _server = serverAndClientCreator.createServer();
+ _httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
+ _port = _server.getConnectors()[0].getLocalPort();
}
@Override
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java
new file mode 100644
index 00000000000..e0410057571
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpAsserts.java
@@ -0,0 +1,29 @@
+package org.eclipse.jetty.client;
+
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jetty.http.HttpFields;
+import org.junit.Assert;
+
+public final class HttpAsserts
+{
+ public static void assertContainsHeaderKey(String expectedKey, HttpFields headers)
+ {
+ if (headers.containsKey(expectedKey))
+ {
+ return;
+ }
+ List names = Collections.list(headers.getFieldNames());
+ StringBuilder err = new StringBuilder();
+ err.append("Missing expected header key [").append(expectedKey);
+ err.append("] (of ").append(names.size()).append(" header fields)");
+ for (int i = 0; i < names.size(); i++)
+ {
+ String value = headers.getStringField(names.get(i));
+ err.append("\n").append(i).append("] ").append(names.get(i));
+ err.append(": ").append(value);
+ }
+ Assert.fail(err.toString());
+ }
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java
index 09de4467204..3b84bfec975 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpExchangeTest.java
@@ -13,14 +13,9 @@
package org.eclipse.jetty.client;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-import static org.junit.matchers.JUnitMatchers.containsString;
+import static org.junit.Assert.*;
+import static org.junit.matchers.JUnitMatchers.*;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -30,13 +25,10 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
+import org.eclipse.jetty.client.helperClasses.HttpServerAndClientCreator;
+import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.eclipse.jetty.client.security.ProxyAuthorization;
import org.eclipse.jetty.http.HttpFields;
-import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.Buffer;
@@ -44,17 +36,13 @@ import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.nio.DirectNIOBuffer;
-import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.handler.AbstractHandler;
-import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.toolchain.test.Stress;
-import org.eclipse.jetty.util.IO;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
+import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.junit.After;
+import org.junit.AfterClass;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
/* ------------------------------------------------------------ */
@@ -63,37 +51,44 @@ import org.junit.Test;
*/
public class HttpExchangeTest
{
- private static final Logger LOG = Log.getLogger(HttpExchangeTest.class);
-
- protected int _maxConnectionsPerAddress = 2;
- protected String _scheme = "http";
- protected Server _server;
- protected int _port;
- protected HttpClient _httpClient;
- protected Connector _connector;
- protected AtomicInteger _count = new AtomicInteger();
+ final static boolean verbose=false;
+ protected static int _maxConnectionsPerAddress = 2;
+ protected static String _scheme = "http";
+ protected static Server _server;
+ protected static int _port;
+ protected static HttpClient _httpClient;
+ protected static AtomicInteger _count = new AtomicInteger();
+ protected static ServerAndClientCreator serverAndClientCreator = new HttpServerAndClientCreator();
+
+ protected static URI getBaseURI()
+ {
+ return URI.create(_scheme + "://localhost:" + _port + "/");
+ }
/* ------------------------------------------------------------ */
+ // TODO work out why BeforeClass does not work here?
@Before
- public void setUp() throws Exception
+ public void setUpOnce() throws Exception
{
- startServer();
- _httpClient=new HttpClient();
- _httpClient.setIdleTimeout(3000);
- _httpClient.setTimeout(3500);
- _httpClient.setConnectTimeout(2000);
- _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
- _httpClient.setMaxConnectionsPerAddress(_maxConnectionsPerAddress);
- _httpClient.start();
+ _scheme = "http";
+ _server = serverAndClientCreator.createServer();
+ _httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
+ _port = _server.getConnectors()[0].getLocalPort();
}
/* ------------------------------------------------------------ */
@After
- public void tearDown() throws Exception
+ public void tearDownOnce() throws Exception
{
_httpClient.stop();
- Thread.sleep(500);
- stopServer();
+ long startTime = System.currentTimeMillis();
+ while (!_httpClient.getState().equals(AbstractLifeCycle.STOPPED))
+ {
+ if (System.currentTimeMillis() - startTime > 1000)
+ break;
+ Thread.sleep(5);
+ }
+ _server.stop();
}
/* ------------------------------------------------------------ */
@@ -110,7 +105,9 @@ public class HttpExchangeTest
{
sender(1,false);
sender(1,true);
-
+ sender(10,false);
+ sender(10,true);
+
if (Stress.isEnabled())
{
sender(100,false);
@@ -118,67 +115,72 @@ public class HttpExchangeTest
sender(10000,false);
sender(10000,true);
}
- else
- {
- sender(10,false);
- sender(10,true);
- }
}
/* ------------------------------------------------------------ */
/**
* Test sending data through the exchange.
- *
+ *
* @throws IOException
*/
- public void sender(final int nb,final boolean close) throws Exception
+ public void sender(final int nb, final boolean close) throws Exception
{
_count.set(0);
- final CountDownLatch complete=new CountDownLatch(nb);
- final CountDownLatch latch=new CountDownLatch(nb);
+ final CountDownLatch complete = new CountDownLatch(nb);
+ final AtomicInteger allcontent = new AtomicInteger(nb);
HttpExchange[] httpExchange = new HttpExchange[nb];
- long start=System.currentTimeMillis();
- for (int i=0; i "+len);
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseComplete()
{
- result="complete";
- if (len==2009)
- latch.countDown();
+ if (verbose)
+ System.err.println("] == "+len+" "+complete.getCount()+"/"+nb);
+ result = "complete";
+ if (len == 2009)
+ allcontent.decrementAndGet();
else
- {
- System.err.println(n+" ONLY "+len);
- }
+ System.err.println(n + " ONLY " + len+ "/2009");
complete.countDown();
}
@@ -207,9 +211,11 @@ public class HttpExchangeTest
@Override
protected void onConnectionFailed(Throwable ex)
{
+ if (verbose)
+ System.err.println("] "+ex);
complete.countDown();
- result="failed";
- System.err.println(n+" FAILED "+ex);
+ result = "failed";
+ System.err.println(n + " FAILED " + ex);
super.onConnectionFailed(ex);
}
@@ -217,9 +223,11 @@ public class HttpExchangeTest
@Override
protected void onException(Throwable ex)
{
+ if (verbose)
+ System.err.println("] "+ex);
complete.countDown();
- result="excepted";
- System.err.println(n+" EXCEPTED "+ex);
+ result = "excepted";
+ System.err.println(n + " EXCEPTED " + ex);
super.onException(ex);
}
@@ -227,9 +235,11 @@ public class HttpExchangeTest
@Override
protected void onExpire()
{
+ if (verbose)
+ System.err.println("] expired");
complete.countDown();
- result="expired";
- System.err.println(n+" EXPIRED "+len);
+ result = "expired";
+ System.err.println(n + " EXPIRED " + len);
super.onExpire();
}
@@ -237,29 +247,24 @@ public class HttpExchangeTest
@Override
public String toString()
{
- return n+" "+result+" "+len;
+ return n+"/"+result+"/"+len+"/"+super.toString();
}
};
- httpExchange[n].setURL(_scheme+"://localhost:"+_port+"/"+n);
+ httpExchange[n].setURI(getBaseURI().resolve("/" + n));
httpExchange[n].addRequestHeader("arbitrary","value");
if (close)
httpExchange[n].setRequestHeader("Connection","close");
_httpClient.send(httpExchange[n]);
}
-
- assertTrue(complete.await(45,TimeUnit.SECONDS));
-
- long elapsed=System.currentTimeMillis()-start;
- // make windows-friendly ... System.currentTimeMillis() on windows is dope!
- /*
- if(elapsed>0)
- System.err.println(nb+"/"+_count+" c="+close+" rate="+(nb*1000/elapsed));
- */
+ if (!complete.await(2,TimeUnit.SECONDS))
+ System.err.println(_httpClient.dump());
- assertEquals("nb="+nb+" close="+close,0,latch.getCount());
+ assertTrue(complete.await(20,TimeUnit.SECONDS));
+
+ assertEquals("nb="+nb+" close="+close,0,allcontent.get());
}
/* ------------------------------------------------------------ */
@@ -269,7 +274,7 @@ public class HttpExchangeTest
for (int i=0;i<20;i++)
{
ContentExchange httpExchange=new ContentExchange();
- httpExchange.setURI(new URI(_scheme, null, "localhost", _port, null, null, null));
+ httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethods.POST);
httpExchange.setRequestContent(new ByteArrayBuffer(""));
_httpClient.send(httpExchange);
@@ -288,12 +293,14 @@ public class HttpExchangeTest
for (int i=0;i<10;i++)
{
ContentExchange httpExchange=new ContentExchange();
- httpExchange.setURI(new URI(_scheme, null, "localhost", _port, "/", "i="+i, null));
+ URI uri = getBaseURI().resolve("?i=" + i);
+ httpExchange.setURI(uri);
httpExchange.setMethod(HttpMethods.GET);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
//httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
+ assertNotNull("Should have received response content", result);
assertEquals("i="+i,0,result.indexOf(""));
assertEquals("i="+i,result.length()-10,result.indexOf(""));
assertEquals(HttpExchange.STATUS_COMPLETED, status);
@@ -308,17 +315,16 @@ public class HttpExchangeTest
for (int i=0;i<10;i++)
{
ContentExchange httpExchange=new ContentExchange();
- httpExchange.setURL(_scheme+"://localhost:"+_port+"/?i="+i);
+ URI uri = getBaseURI().resolve("?i=" + i);
+ httpExchange.setURI(uri);
httpExchange.setMethod(HttpMethods.GET);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
assertNotNull(httpExchange.getLocalAddress());
- //System.out.println("Local Address: " + httpExchange.getLocalAddress());
-
- //httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result=httpExchange.getResponseContent();
+ assertNotNull("Should have received response content", result);
assertEquals("i="+i,0,result.indexOf(""));
assertEquals("i="+i,result.length()-10,result.indexOf(""));
assertEquals(HttpExchange.STATUS_COMPLETED, status);
@@ -355,7 +361,7 @@ public class HttpExchangeTest
throwable.set(x);
}
};
- httpExchange.setURL(_scheme+"://localhost:"+_port+"/");
+ httpExchange.setURI(getBaseURI());
httpExchange.setMethod("SLEEP");
_httpClient.send(httpExchange);
new Thread()
@@ -374,6 +380,7 @@ public class HttpExchangeTest
System.err.println(throwable.get());
assertTrue(throwable.get().toString().indexOf("close")>=0);
assertEquals(HttpExchange.STATUS_EXCEPTED, status);
+ _httpClient.start();
}
/* ------------------------------------------------------------ */
@@ -381,7 +388,54 @@ public class HttpExchangeTest
public void testBigPostWithContentExchange() throws Exception
{
int size =32;
- ContentExchange httpExchange=new ContentExchange();
+ ContentExchange httpExchange=new ContentExchange()
+ {
+ int total;
+
+ @Override
+ protected synchronized void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
+ {
+ if (verbose)
+ System.err.println("] "+version+" "+status+" "+reason);
+ super.onResponseStatus(version,status,reason);
+ }
+
+ @Override
+ protected synchronized void onResponseHeader(Buffer name, Buffer value) throws IOException
+ {
+ if (verbose)
+ System.err.println("] "+name+": "+value);
+ super.onResponseHeader(name,value);
+ }
+
+ @Override
+ protected synchronized void onResponseContent(Buffer content) throws IOException
+ {
+ if (verbose)
+ {
+ total+=content.length();
+ System.err.println("] "+content.length()+" -> "+total);
+ }
+ super.onResponseContent(content);
+ }
+
+ @Override
+ protected void onRequestComplete() throws IOException
+ {
+ if (verbose)
+ System.err.println("] ==");
+ super.onRequestComplete();
+ }
+
+ @Override
+ protected void onResponseHeaderComplete() throws IOException
+ {
+ if (verbose)
+ System.err.println("] --");
+ super.onResponseHeaderComplete();
+ }
+
+ };
Buffer babuf = new ByteArrayBuffer(size*36*1024);
Buffer niobuf = new DirectNIOBuffer(size*36*1024);
@@ -394,28 +448,27 @@ public class HttpExchangeTest
niobuf.put(bytes);
}
- httpExchange.setURL(_scheme+"://localhost:"+_port+"/");
+ httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethods.POST);
httpExchange.setRequestContentType("application/data");
httpExchange.setRequestContent(babuf);
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
-
assertEquals(HttpExchange.STATUS_COMPLETED,status);
String result=httpExchange.getResponseContent();
assertEquals(babuf.length(),result.length());
httpExchange.reset();
- httpExchange.setURL(_scheme+"://localhost:"+_port+"/");
+ httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethods.POST);
httpExchange.setRequestContentType("application/data");
httpExchange.setRequestContent(niobuf);
_httpClient.send(httpExchange);
status = httpExchange.waitForDone();
+ assertEquals(HttpExchange.STATUS_COMPLETED, status);
result=httpExchange.getResponseContent();
assertEquals(niobuf.length(),result.length());
- assertEquals(HttpExchange.STATUS_COMPLETED, status);
}
/* ------------------------------------------------------------ */
@@ -426,7 +479,7 @@ public class HttpExchangeTest
{
};
- httpExchange.setURL(_scheme+"://localhost:"+_port);
+ httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethods.POST);
final String data="012345678901234567890123456789012345678901234567890123456789";
@@ -447,7 +500,7 @@ public class HttpExchangeTest
@Override
public int read(byte[] b, int off, int len) throws IOException
{
- if (_index>=data.length())
+ if (_index >= data.length())
return -1;
try
@@ -458,28 +511,28 @@ public class HttpExchangeTest
{
e.printStackTrace();
}
-
- int l=0;
- while (l<5 && _index=0)
+ while ((len = in.read(buffer)) >= 0)
{
out.write(buffer,0,len);
}
}
catch (EofException e)
{
- System.err.println("HttpExchangeTest#copyStream: "+e);
+ System.err.println("HttpExchangeTest#copyStream: " + e);
}
catch (IOException e)
{
e.printStackTrace();
}
}
-
- /* ------------------------------------------------------------ */
- protected void newServer() throws Exception
- {
- _server=new Server();
- _server.setGracefulShutdown(500);
- _connector=new SelectChannelConnector();
-
- _connector.setMaxIdleTime(3000000);
-
- _connector.setPort(0);
- _server.setConnectors(new Connector[] { _connector });
- }
-
- /* ------------------------------------------------------------ */
- protected void startServer() throws Exception
- {
- newServer();
- _server.setHandler(new AbstractHandler()
- {
- public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
- {
- int i=0;
- try
- {
- baseRequest.setHandled(true);
- response.setStatus(200);
- _count.incrementAndGet();
-
- if (request.getServerName().equals("jetty.eclipse.org"))
- {
- response.getOutputStream().println("Proxy request: "+request.getRequestURL());
- response.getOutputStream().println(request.getHeader(HttpHeaders.PROXY_AUTHORIZATION));
- }
- else if (request.getMethod().equalsIgnoreCase("GET"))
- {
- response.getOutputStream().println("");
- for (; i<100; i++)
- {
- response.getOutputStream().println(" "+i+"");
- }
- else if (request.getMethod().equalsIgnoreCase("OPTIONS"))
- {
- if ("*".equals(target))
- {
- response.setContentLength(0);
- response.setHeader("Allow","GET,HEAD,POST,PUT,DELETE,MOVE,OPTIONS,TRACE");
- }
- }
- else if (request.getMethod().equalsIgnoreCase("SLEEP"))
- {
- Thread.sleep(10000);
- }
- else
- {
- response.setContentType(request.getContentType());
- int size=request.getContentLength();
- ByteArrayOutputStream bout = new ByteArrayOutputStream(size>0?size:32768);
- IO.copy(request.getInputStream(),bout);
- response.getOutputStream().write(bout.toByteArray());
- }
- }
- catch(InterruptedException e)
- {
- LOG.debug(e);
- }
- catch(IOException e)
- {
- e.printStackTrace();
- throw e;
- }
- catch(Throwable e)
- {
- e.printStackTrace();
- throw new ServletException(e);
- }
- finally
- {
- }
- }
- });
- _server.start();
- _port=_connector.getLocalPort();
- }
-
- /* ------------------------------------------------------------ */
- private void stopServer() throws Exception
- {
- _server.stop();
- }
-
}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/SslHttpExchangeTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/SslHttpExchangeTest.java
index 6ea97bc5aa4..8ec13c1ef21 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/SslHttpExchangeTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/SslHttpExchangeTest.java
@@ -13,67 +13,36 @@
package org.eclipse.jetty.client;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.not;
+import static org.hamcrest.Matchers.*;
-import org.eclipse.jetty.http.ssl.SslContextFactory;
+import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
+import org.eclipse.jetty.client.helperClasses.SslServerAndClientCreator;
import org.eclipse.jetty.server.Connector;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ssl.SslSocketConnector;
-import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.OS;
import org.eclipse.jetty.toolchain.test.Stress;
import org.junit.Assume;
import org.junit.Before;
+import org.junit.BeforeClass;
import org.junit.Test;
/**
* Functional testing for HttpExchange.
- *
- *
- *
*/
public class SslHttpExchangeTest extends HttpExchangeTest
{
+ protected static ServerAndClientCreator serverAndClientCreator = new SslServerAndClientCreator();
+
/* ------------------------------------------------------------ */
@Before
- @Override
- public void setUp() throws Exception
+ public void setUpOnce() throws Exception
{
_scheme="https";
- startServer();
- _httpClient=new HttpClient();
- _httpClient.setIdleTimeout(2000);
- _httpClient.setTimeout(2500);
- _httpClient.setConnectTimeout(1000);
- _httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
- _httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
- _httpClient.setMaxConnectionsPerAddress(2);
- _httpClient.start();
+ _server = serverAndClientCreator.createServer();
+ _httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
+ Connector[] connectors = _server.getConnectors();
+ _port = connectors[0].getLocalPort();
}
- /* ------------------------------------------------------------ */
- @Override
- protected void newServer()
- {
- _server = new Server();
- //SslSelectChannelConnector connector = new SslSelectChannelConnector();
- SslSocketConnector connector = new SslSocketConnector();
-
- String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
-
- connector.setPort(0);
- SslContextFactory cf = connector.getSslContextFactory();
- cf.setKeyStore(keystore);
- cf.setKeyStorePassword("storepwd");
- cf.setKeyManagerPassword("keypwd");
- connector.setAllowRenegotiate(true);
-
- _server.setConnectors(new Connector[]
- { connector });
- _connector=connector;
- }
-
/* ------------------------------------------------------------ */
private void IgnoreTestOnBuggyIBM()
{
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AbstractSslServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AbstractSslServerAndClientCreator.java
new file mode 100644
index 00000000000..d7df2a39168
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AbstractSslServerAndClientCreator.java
@@ -0,0 +1,57 @@
+// ========================================================================
+// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+
+package org.eclipse.jetty.client.helperClasses;
+
+import org.eclipse.jetty.http.ssl.SslContextFactory;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
+import org.eclipse.jetty.server.ssl.SslSocketConnector;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+
+/* ------------------------------------------------------------ */
+/**
+ */
+public abstract class AbstractSslServerAndClientCreator implements ServerAndClientCreator
+{
+ private static final Logger LOG = Log.getLogger(AbstractSslServerAndClientCreator.class);
+
+ /* ------------------------------------------------------------ */
+ public Server createServer() throws Exception
+ {
+ Server server = new Server();
+ //SslSelectChannelConnector connector = new SslSelectChannelConnector();
+ SslSocketConnector connector = new SslSocketConnector();
+
+ String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
+
+ connector.setPort(0);
+ SslContextFactory cf = connector.getSslContextFactory();
+ cf.setKeyStore(keystore);
+ cf.setKeyStorePassword("storepwd");
+ cf.setKeyManagerPassword("keypwd");
+ connector.setAllowRenegotiate(true);
+
+ server.setConnectors(new Connector[]{ connector });
+ server.setHandler(new GenericServerHandler());
+ server.start();
+ return server;
+ }
+
+
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java
new file mode 100644
index 00000000000..6d08d216f90
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/AsyncSslServerAndClientCreator.java
@@ -0,0 +1,26 @@
+package org.eclipse.jetty.client.helperClasses;
+
+import java.io.FileInputStream;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+
+public class AsyncSslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator
+{
+
+ /* ------------------------------------------------------------ */
+ public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
+ {
+ HttpClient httpClient = new HttpClient();
+ httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
+ httpClient.setMaxConnectionsPerAddress(2);
+
+ String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
+ httpClient.setKeyStoreInputStream(new FileInputStream(keystore));
+ httpClient.setKeyStorePassword("storepwd");
+ httpClient.setKeyManagerPassword("keypwd");
+ httpClient.start();
+ return httpClient;
+ }
+
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java
new file mode 100644
index 00000000000..584f4b1a64b
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ExternalKeyStoreAsyncSslServerAndClientCreator.java
@@ -0,0 +1,27 @@
+package org.eclipse.jetty.client.helperClasses;
+
+import java.io.FileInputStream;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+
+public class ExternalKeyStoreAsyncSslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator
+{
+
+ public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
+ {
+ HttpClient httpClient = new HttpClient();
+ httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
+ httpClient.setMaxConnectionsPerAddress(2);
+
+ String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
+
+ httpClient.setKeyStoreInputStream(new FileInputStream(keystore));
+ httpClient.setKeyStorePassword("storepwd");
+ httpClient.setKeyManagerPassword("keypwd");
+ httpClient.start();
+ return httpClient;
+ }
+
+
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java
new file mode 100644
index 00000000000..82dbdb35c47
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/GenericServerHandler.java
@@ -0,0 +1,84 @@
+package org.eclipse.jetty.client.helperClasses;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.eclipse.jetty.http.HttpHeaders;
+import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.handler.AbstractHandler;
+import org.eclipse.jetty.util.IO;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+
+/**
+ * Generic Server Handler used for various client tests.
+ */
+public class GenericServerHandler extends AbstractHandler
+{
+ private static final Logger LOG = Log.getLogger(GenericServerHandler.class);
+
+ public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
+ {
+ int i = 0;
+ try
+ {
+ baseRequest.setHandled(true);
+ response.setStatus(200);
+
+ if (request.getServerName().equals("jetty.eclipse.org"))
+ {
+ response.getOutputStream().println("Proxy request: " + request.getRequestURL());
+ response.getOutputStream().println(request.getHeader(HttpHeaders.PROXY_AUTHORIZATION));
+ }
+ else if (request.getMethod().equalsIgnoreCase("GET"))
+ {
+ response.getOutputStream().println("");
+ for (; i < 100; i++)
+ {
+ response.getOutputStream().println(" " + i + "");
+ }
+ else if (request.getMethod().equalsIgnoreCase("OPTIONS"))
+ {
+ if ("*".equals(target))
+ {
+ response.setContentLength(0);
+ response.setHeader("Allow","GET,HEAD,POST,PUT,DELETE,MOVE,OPTIONS,TRACE");
+ }
+ }
+ else if (request.getMethod().equalsIgnoreCase("SLEEP"))
+ {
+ Thread.sleep(10000);
+ }
+ else
+ {
+ response.setContentType(request.getContentType());
+ int size = request.getContentLength();
+ ByteArrayOutputStream bout = new ByteArrayOutputStream(size > 0?size:32768);
+ IO.copy(request.getInputStream(),bout);
+ response.getOutputStream().write(bout.toByteArray());
+ }
+ }
+ catch (InterruptedException e)
+ {
+ LOG.debug(e);
+ }
+ catch (IOException e)
+ {
+ LOG.warn(e);
+ throw e;
+ }
+ catch (Throwable e)
+ {
+ LOG.warn(e);
+ throw new ServletException(e);
+ }
+ }
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java
new file mode 100644
index 00000000000..d9a2f1d3eef
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/HttpServerAndClientCreator.java
@@ -0,0 +1,36 @@
+package org.eclipse.jetty.client.helperClasses;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.nio.SelectChannelConnector;
+
+public class HttpServerAndClientCreator implements ServerAndClientCreator
+{
+ public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
+ {
+ HttpClient httpClient = new HttpClient();
+ httpClient.setIdleTimeout(idleTimeout);
+ httpClient.setTimeout(timeout);
+ httpClient.setConnectTimeout(connectTimeout);
+ httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
+ httpClient.setMaxConnectionsPerAddress(2);
+ httpClient.start();
+ return httpClient;
+ }
+
+ public Server createServer() throws Exception
+ {
+ Server _server = new Server();
+ _server.setGracefulShutdown(500);
+ Connector _connector = new SelectChannelConnector();
+
+ _connector.setMaxIdleTime(3000000);
+
+ _connector.setPort(0);
+ _server.setConnectors(new Connector[]{ _connector });
+ _server.setHandler(new GenericServerHandler());
+ _server.start();
+ return _server;
+ }
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java
new file mode 100644
index 00000000000..015006f6802
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/ServerAndClientCreator.java
@@ -0,0 +1,11 @@
+package org.eclipse.jetty.client.helperClasses;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.server.Server;
+
+public interface ServerAndClientCreator
+{
+ Server createServer() throws Exception;
+
+ HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception;
+}
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java
new file mode 100644
index 00000000000..d0e0ad0a115
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/helperClasses/SslServerAndClientCreator.java
@@ -0,0 +1,19 @@
+package org.eclipse.jetty.client.helperClasses;
+
+import org.eclipse.jetty.client.HttpClient;
+
+public class SslServerAndClientCreator extends AbstractSslServerAndClientCreator implements ServerAndClientCreator
+{
+
+ public HttpClient createClient(long idleTimeout, long timeout, int connectTimeout) throws Exception
+ {
+ HttpClient httpClient = new HttpClient();
+ httpClient.setIdleTimeout(idleTimeout);
+ httpClient.setTimeout(timeout);
+ httpClient.setConnectTimeout(connectTimeout);
+ httpClient.setConnectorType(HttpClient.CONNECTOR_SOCKET);
+ httpClient.setMaxConnectionsPerAddress(2);
+ httpClient.start();
+ return httpClient;
+ }
+}
diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml
index 46cad3e98eb..e49d6d28c9c 100644
--- a/jetty-distribution/pom.xml
+++ b/jetty-distribution/pom.xml
@@ -155,157 +155,6 @@
maven-dependency-plugin
-
- unpack
- generate-resources
-
- unpack
-
-
-
-
- org.eclipse.jetty
- jetty-rewrite
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-ajp
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- test-jetty-webapp
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-jmx
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-util
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-webapp
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-deploy
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-plus
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-server
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-security
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-policy
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-monitor
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-overlay-deployer
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
- org.eclipse.jetty
- jetty-annotations
- ${project.version}
- config
- jar
- true
- **
- ${assembly-directory}
-
-
-
- copygenerate-resources
@@ -324,187 +173,6 @@
${assembly-directory}/VERSION.txt
-
- org.eclipse.jetty
- jetty-util
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-io
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-http
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-server
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-security
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-servlet
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-servlets
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-xml
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-webapp
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
-
- org.eclipse.jetty
- jetty-deploy
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-jmx
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-rewrite
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-ajp
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-annotations
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-client
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-jndi
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-policy
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-monitor
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib/monitor
-
-
- org.eclipse.jetty
- jetty-plus
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-continuation
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
- org.eclipse.jettytest-jetty-webapp
@@ -525,36 +193,77 @@
${assembly-directory}start.jar
-
- org.eclipse.jetty
- jetty-overlay-deployer
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-overlay-deployer
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
-
- org.eclipse.jetty
- jetty-websocket
- ${project.version}
- jar
- true
- **
- ${assembly-directory}/lib
-
+
+ copy-lib-deps
+ generate-resources
+
+ copy-dependencies
+
+
+ org.eclipse.jetty
+ jetty-start,jetty-monitor,jetty-jsp-2.1
+ jar
+ ${assembly-directory}/lib
+
+
+
+ copy-lib-jsp-deps
+ generate-resources
+
+ copy-dependencies
+
+
+ org.eclipse.jetty,org.glassfish.web
+ jetty-jsp-2.1,jsp-impl
+ jar
+ ${assembly-directory}/lib/jsp
+
+
+
+ copy-lib-monitor-deps
+ generate-resources
+
+ copy-dependencies
+
+
+ org.eclipse.jetty
+ jetty-monitor
+ jar
+ true
+ ${assembly-directory}/lib/monitor
+
+
+
+ unpack-config-deps
+ generate-resources
+
+ unpack-dependencies
+
+
+ org.eclipse.jetty
+ config
+ false
+ ${assembly-directory}
+
+
+
+ unpack-javadoc
+ generate-resources
+
+ unpack-dependencies
+
+
+
+ org.eclipse.jetty.aggregate
+ jetty-all
+ javadoc
+ true
+ ${assembly-directory}/javadoc
+
+
@@ -663,12 +372,12 @@
org.eclipse.jetty
- jetty-overlay-deployer
+ jetty-servlets${project.version}org.eclipse.jetty
- jetty-overlay-deployer
+ jetty-monitor${project.version}
@@ -676,5 +385,17 @@
jetty-websocket${project.version}
+
+ org.eclipse.jetty
+ jetty-overlay-deployer
+ ${project.version}
+
+
+ org.eclipse.jetty.aggregate
+ jetty-all
+ javadoc
+ jar
+ ${project.version}
+
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
index aecc18b069c..0c18400950b 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/HttpParser.java
@@ -266,9 +266,19 @@ public class HttpParser implements Parser
// Fill buffer if we can
if (length == 0)
{
- long filled=fill();
+ long filled=-1;
+ IOException ex=null;
+ try
+ {
+ filled=fill();
+ }
+ catch(IOException e)
+ {
+ LOG.debug(this.toString(),e);
+ ex=e;
+ }
- if (filled < 0)
+ if (filled < 0 || _endp.isInputShutdown())
{
if (_headResponse && _state>STATE_END)
{
@@ -291,6 +301,8 @@ public class HttpParser implements Parser
return 1;
}
+ if (ex!=null)
+ throw ex;
return -1;
}
length=_buffer.length();
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java b/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java
index 7e24daa3ebf..19da9e00104 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/PathMap.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.http;
@@ -34,7 +34,7 @@ import org.eclipse.jetty.util.URIUtil;
* /foo/bar - an exact path specification.
* /foo/* - a prefix path specification (must end '/*').
* *.ext - a suffix path specification.
- * / - the default path specification.
+ * / - the default path specification.
*
* Matching is performed in the following order
*
* Multiple path specifications can be mapped by providing a list of
- * specifications. By default this class uses characters ":," as path
- * separators, unless configured differently by calling the static
- * method @see PathMap#setPathSpecSeparators(String)
+ * specifications. By default this class uses characters ":," as path
+ * separators, unless configured differently by calling the static
+ * method @see PathMap#setPathSpecSeparators(String)
*
* Special characters within paths such as '?� and ';' are not treated specially
- * as it is assumed they would have been either encoded in the original URL or
+ * as it is assumed they would have been either encoded in the original URL or
* stripped from the path.
*
* This class is not synchronized. If concurrent modifications are
* possible then it should be synchronized at a higher level.
*
- *
+ *
*/
public class PathMap extends HashMap implements Externalizable
{
/* ------------------------------------------------------------ */
private static String __pathSpecSeparators = ":,";
-
+
/* ------------------------------------------------------------ */
/** Set the path spec separator.
* Multiple path specification may be included in a single string
@@ -72,7 +72,7 @@ public class PathMap extends HashMap implements Externalizable
{
__pathSpecSeparators=s;
}
-
+
/* --------------------------------------------------------------- */
final StringMap _prefixMap=new StringMap();
final StringMap _suffixMap=new StringMap();
@@ -83,7 +83,7 @@ public class PathMap extends HashMap implements Externalizable
Entry _default=null;
final Set _entrySet;
boolean _nodefault=false;
-
+
/* --------------------------------------------------------------- */
/** Construct empty PathMap.
*/
@@ -102,7 +102,7 @@ public class PathMap extends HashMap implements Externalizable
_entrySet=entrySet();
_nodefault=nodefault;
}
-
+
/* --------------------------------------------------------------- */
/** Construct empty PathMap.
*/
@@ -111,7 +111,7 @@ public class PathMap extends HashMap implements Externalizable
super (capacity);
_entrySet=entrySet();
}
-
+
/* --------------------------------------------------------------- */
/** Construct from dictionary PathMap.
*/
@@ -120,7 +120,7 @@ public class PathMap extends HashMap implements Externalizable
putAll(m);
_entrySet=entrySet();
}
-
+
/* ------------------------------------------------------------ */
public void writeExternal(java.io.ObjectOutput out)
throws java.io.IOException
@@ -128,7 +128,7 @@ public class PathMap extends HashMap implements Externalizable
HashMap map = new HashMap(this);
out.writeObject(map);
}
-
+
/* ------------------------------------------------------------ */
public void readExternal(java.io.ObjectInput in)
throws java.io.IOException, ClassNotFoundException
@@ -136,7 +136,7 @@ public class PathMap extends HashMap implements Externalizable
HashMap map = (HashMap)in.readObject();
this.putAll(map);
}
-
+
/* --------------------------------------------------------------- */
/** Add a single path match to the PathMap.
* @param pathSpec The path specification, or comma separated list of
@@ -148,16 +148,16 @@ public class PathMap extends HashMap implements Externalizable
{
StringTokenizer tok = new StringTokenizer(pathSpec.toString(),__pathSpecSeparators);
Object old =null;
-
+
while (tok.hasMoreTokens())
{
String spec=tok.nextToken();
-
+
if (!spec.startsWith("/") && !spec.startsWith("*."))
throw new IllegalArgumentException("PathSpec "+spec+". must start with '/' or '*.'");
-
+
old = super.put(spec,object);
-
+
// Make entry that was just created.
Entry entry = new Entry(spec,object);
@@ -176,7 +176,7 @@ public class PathMap extends HashMap implements Externalizable
else if (spec.startsWith("*."))
_suffixMap.put(spec.substring(2),entry);
else if (spec.equals(URIUtil.SLASH))
- {
+ {
if (_nodefault)
_exactMap.put(spec,entry);
else
@@ -193,7 +193,7 @@ public class PathMap extends HashMap implements Externalizable
}
}
}
-
+
return old;
}
@@ -209,8 +209,8 @@ public class PathMap extends HashMap implements Externalizable
return entry.getValue();
return null;
}
-
-
+
+
/* --------------------------------------------------------------- */
/** Get the entry mapped by the best specification.
* @param path the path.
@@ -222,14 +222,14 @@ public class PathMap extends HashMap implements Externalizable
if (path==null)
return null;
-
- int l=path.length();
+
+ int l=path.length();
// try exact match
entry=_exactMap.getEntry(path,0,l);
if (entry!=null)
return (Entry) entry.getValue();
-
+
// prefix search
int i=l;
while((i=path.lastIndexOf('/',i-1))>=0)
@@ -238,11 +238,11 @@ public class PathMap extends HashMap implements Externalizable
if (entry!=null)
return (Entry) entry.getValue();
}
-
+
// Prefix Default
if (_prefixDefault!=null)
return _prefixDefault;
-
+
// Extension search
i=0;
while ((i=path.indexOf('.',i+1))>0)
@@ -250,12 +250,12 @@ public class PathMap extends HashMap implements Externalizable
entry=_suffixMap.getEntry(path,i+1,l-i-1);
if (entry!=null)
return (Entry) entry.getValue();
- }
-
+ }
+
// Default
return _default;
}
-
+
/* --------------------------------------------------------------- */
/** Get all entries matched by the path.
* Best match first.
@@ -263,20 +263,20 @@ public class PathMap extends HashMap implements Externalizable
* @return LazyList of Map.Entry instances key=pathSpec
*/
public Object getLazyMatches(String path)
- {
+ {
Map.Entry entry;
Object entries=null;
if (path==null)
return LazyList.getList(entries);
-
+
int l=path.length();
// try exact match
entry=_exactMap.getEntry(path,0,l);
if (entry!=null)
entries=LazyList.add(entries,entry.getValue());
-
+
// prefix search
int i=l-1;
while((i=path.lastIndexOf('/',i-1))>=0)
@@ -285,11 +285,11 @@ public class PathMap extends HashMap implements Externalizable
if (entry!=null)
entries=LazyList.add(entries,entry.getValue());
}
-
+
// Prefix Default
if (_prefixDefault!=null)
entries=LazyList.add(entries,_prefixDefault);
-
+
// Extension search
i=0;
while ((i=path.indexOf('.',i+1))>0)
@@ -305,13 +305,13 @@ public class PathMap extends HashMap implements Externalizable
// Optimization for just the default
if (entries==null)
return _defaultSingletonList;
-
+
entries=LazyList.add(entries,_default);
}
-
+
return entries;
}
-
+
/* --------------------------------------------------------------- */
/** Get all entries matched by the path.
* Best match first.
@@ -319,7 +319,7 @@ public class PathMap extends HashMap implements Externalizable
* @return List of Map.Entry instances key=pathSpec
*/
public List getMatches(String path)
- {
+ {
return LazyList.getList(getLazyMatches(path));
}
@@ -330,12 +330,12 @@ public class PathMap extends HashMap implements Externalizable
* @return Whether the PathMap contains any entries that match this
*/
public boolean containsMatch(String path)
- {
+ {
Entry match = getMatch(path);
return match!=null && !match.equals(_default);
}
- /* --------------------------------------------------------------- */
+ /* --------------------------------------------------------------- */
@Override
public Object remove(Object pathSpec)
{
@@ -362,7 +362,7 @@ public class PathMap extends HashMap implements Externalizable
}
return super.remove(pathSpec);
}
-
+
/* --------------------------------------------------------------- */
@Override
public void clear()
@@ -374,7 +374,7 @@ public class PathMap extends HashMap implements Externalizable
_defaultSingletonList=null;
super.clear();
}
-
+
/* --------------------------------------------------------------- */
/**
* @return true if match.
@@ -397,7 +397,7 @@ public class PathMap extends HashMap implements Externalizable
{
if (!noDefault && pathSpec.length()==1 || pathSpec.equals(path))
return true;
-
+
if(isPathWildcardMatch(pathSpec, path))
return true;
}
@@ -419,24 +419,24 @@ public class PathMap extends HashMap implements Externalizable
}
return false;
}
-
-
+
+
/* --------------------------------------------------------------- */
/** Return the portion of a path that matches a path spec.
* @return null if no match at all.
*/
public static String pathMatch(String pathSpec, String path)
- {
+ {
char c = pathSpec.charAt(0);
-
+
if (c=='/')
{
if (pathSpec.length()==1)
return path;
-
+
if (pathSpec.equals(path))
return path;
-
+
if (isPathWildcardMatch(pathSpec, path))
return path.substring(0,pathSpec.length()-2);
}
@@ -448,7 +448,7 @@ public class PathMap extends HashMap implements Externalizable
}
return null;
}
-
+
/* --------------------------------------------------------------- */
/** Return the portion of a path that is after a path spec.
* @return The path info string
@@ -456,12 +456,12 @@ public class PathMap extends HashMap implements Externalizable
public static String pathInfo(String pathSpec, String path)
{
char c = pathSpec.charAt(0);
-
+
if (c=='/')
{
if (pathSpec.length()==1)
return null;
-
+
boolean wildcard = isPathWildcardMatch(pathSpec, path);
// handle the case where pathSpec uses a wildcard and path info is "/*"
@@ -474,7 +474,7 @@ public class PathMap extends HashMap implements Externalizable
return null;
return path.substring(pathSpec.length()-2);
}
- }
+ }
return null;
}
@@ -484,7 +484,7 @@ public class PathMap extends HashMap implements Externalizable
* @param base The base the path is relative to.
* @param pathSpec The spec of the path segment to ignore.
* @param path the additional path
- * @return base plus path with pathspec removed
+ * @return base plus path with pathspec removed
*/
public static String relativePath(String base,
String pathSpec,
@@ -508,7 +508,7 @@ public class PathMap extends HashMap implements Externalizable
path = base + URIUtil.SLASH + info;
return path;
}
-
+
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
@@ -516,7 +516,7 @@ public class PathMap extends HashMap implements Externalizable
{
private final Object key;
private final Object value;
- private String mapped;
+ private String mapped;
private transient String string;
Entry(Object key, Object value)
@@ -529,7 +529,7 @@ public class PathMap extends HashMap implements Externalizable
{
return key;
}
-
+
public Object getValue()
{
return value;
diff --git a/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java b/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java
index 52cecaaad1b..90227c88073 100644
--- a/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java
+++ b/jetty-http/src/main/java/org/eclipse/jetty/http/ssl/SslContextFactory.java
@@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.net.InetAddress;
import java.security.InvalidParameterException;
import java.security.KeyStore;
import java.security.SecureRandom;
@@ -42,7 +43,10 @@ import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLSessionContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLServerSocketFactory;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509KeyManager;
@@ -51,6 +55,8 @@ import javax.net.ssl.X509TrustManager;
import org.eclipse.jetty.http.security.Password;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.security.CertificateUtils;
import org.eclipse.jetty.util.security.CertificateValidator;
@@ -65,6 +71,8 @@ import org.eclipse.jetty.util.security.CertificateValidator;
*/
public class SslContextFactory extends AbstractLifeCycle
{
+ private static final Logger LOG = Log.getLogger(SslContextFactory.class);
+
public static final String DEFAULT_KEYMANAGERFACTORY_ALGORITHM =
(Security.getProperty("ssl.KeyManagerFactory.algorithm") == null ?
"SunX509" : Security.getProperty("ssl.KeyManagerFactory.algorithm"));
@@ -82,8 +90,14 @@ public class SslContextFactory extends AbstractLifeCycle
/** String name of keystore password property. */
public static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password";
+ /** Excluded protocols. */
+ private final Set _excludeProtocols = new HashSet();
+ // private final Set _excludeProtocols = new HashSet(Collections.singleton("SSLv2Hello"));
+ /** Included protocols. */
+ private Set _includeProtocols = null;
+
/** Excluded cipher suites. */
- private Set _excludeCipherSuites = null;
+ private final Set _excludeCipherSuites = new HashSet();
/** Included cipher suites. */
private Set _includeCipherSuites = null;
@@ -196,6 +210,7 @@ public class SslContextFactory extends AbstractLifeCycle
if (_keyStoreInputStream == null && _keyStorePath == null &&
_trustStoreInputStream == null && _trustStorePath == null )
{
+ LOG.debug("No keystore or trust store configured. ACCEPTING UNTRUSTED CERTIFICATES!!!!!");
// Create a trust manager that does not validate certificate chains
TrustManager trustAllCerts = new X509TrustManager()
{
@@ -218,11 +233,115 @@ public class SslContextFactory extends AbstractLifeCycle
}
else
{
- createSSLContext();
+ // verify that keystore and truststore
+ // parameters are set up correctly
+ try
+ {
+ checkKeyStore();
+ }
+ catch(IllegalStateException e)
+ {
+ LOG.ignore(e);
+ }
+
+ KeyStore keyStore = loadKeyStore();
+ KeyStore trustStore = loadTrustStore();
+
+ Collection extends CRL> crls = loadCRL(_crlPath);
+
+ if (_validateCerts && keyStore != null)
+ {
+ if (_certAlias == null)
+ {
+ List aliases = Collections.list(keyStore.aliases());
+ _certAlias = aliases.size() == 1 ? aliases.get(0) : null;
+ }
+
+ Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
+ if (cert == null)
+ {
+ throw new Exception("No certificate found in the keystore" + (_certAlias==null ? "":" for alias " + _certAlias));
+ }
+
+ CertificateValidator validator = new CertificateValidator(trustStore, crls);
+ validator.setMaxCertPathLength(_maxCertPathLength);
+ validator.setEnableCRLDP(_enableCRLDP);
+ validator.setEnableOCSP(_enableOCSP);
+ validator.setOcspResponderURL(_ocspResponderURL);
+ validator.validate(keyStore, cert);
+ }
+
+ KeyManager[] keyManagers = getKeyManagers(keyStore);
+ TrustManager[] trustManagers = getTrustManagers(trustStore,crls);
+
+ SecureRandom secureRandom = (_secureRandomAlgorithm == null)?null:SecureRandom.getInstance(_secureRandomAlgorithm);
+ _context = (_sslProvider == null)?SSLContext.getInstance(_sslProtocol):SSLContext.getInstance(_sslProtocol,_sslProvider);
+ _context.init(keyManagers,trustManagers,secureRandom);
+
+ SSLEngine engine=newSslEngine();
+ LOG.info("Enabled Protocols {} of {}",Arrays.asList(engine.getEnabledProtocols()),Arrays.asList(engine.getSupportedProtocols()));
+ LOG.debug("Enabled Ciphers {} of {}",Arrays.asList(engine.getEnabledCipherSuites()),Arrays.asList(engine.getSupportedCipherSuites()));
}
}
}
+ /* ------------------------------------------------------------ */
+ /**
+ * @return The array of protocol names to exclude from
+ * {@link SSLEngine#setEnabledProtocols(String[])}
+ */
+ public String[] getExcludeProtocols()
+ {
+ return _excludeProtocols.toArray(new String[_excludeProtocols.size()]);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param Protocols
+ * The array of protocol names to exclude from
+ * {@link SSLEngine#setEnabledProtocols(String[])}
+ */
+ public void setExcludeProtocols(String... protocols)
+ {
+ checkNotStarted();
+
+ _excludeProtocols.clear();
+ _excludeProtocols.addAll(Arrays.asList(protocols));
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param protocol Protocol names to add to {@link SSLEngine#setEnabledProtocols(String[])}
+ */
+ public void addExcludeProtocols(String... protocol)
+ {
+ checkNotStarted();
+ _excludeProtocols.addAll(Arrays.asList(protocol));
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @return The array of protocol names to include in
+ * {@link SSLEngine#setEnabledProtocols(String[])}
+ */
+ public String[] getIncludeProtocols()
+ {
+ return _includeProtocols.toArray(new String[_includeProtocols.size()]);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param Protocols
+ * The array of protocol names to include in
+ * {@link SSLEngine#setEnabledProtocols(String[])}
+ */
+ public void setIncludeProtocols(String... protocols)
+ {
+ checkNotStarted();
+
+ _includeProtocols = new HashSet(Arrays.asList(protocols));
+ }
+
/* ------------------------------------------------------------ */
/**
* @return The array of cipher suite names to exclude from
@@ -239,11 +358,21 @@ public class SslContextFactory extends AbstractLifeCycle
* The array of cipher suite names to exclude from
* {@link SSLEngine#setEnabledCipherSuites(String[])}
*/
- public void setExcludeCipherSuites(String[] cipherSuites)
+ public void setExcludeCipherSuites(String... cipherSuites)
{
- checkStarted();
-
- _excludeCipherSuites = new HashSet(Arrays.asList(cipherSuites));
+ checkNotStarted();
+ _excludeCipherSuites.clear();
+ _excludeCipherSuites.addAll(Arrays.asList(cipherSuites));
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * @param cipher Cipher names to add to {@link SSLEngine#setEnabledCipherSuites(String[])}
+ */
+ public void addExcludeCipherSuites(String... cipher)
+ {
+ checkNotStarted();
+ _excludeCipherSuites.addAll(Arrays.asList(cipher));
}
/* ------------------------------------------------------------ */
@@ -262,9 +391,9 @@ public class SslContextFactory extends AbstractLifeCycle
* The array of cipher suite names to include in
* {@link SSLEngine#setEnabledCipherSuites(String[])}
*/
- public void setIncludeCipherSuites(String[] cipherSuites)
+ public void setIncludeCipherSuites(String... cipherSuites)
{
- checkStarted();
+ checkNotStarted();
_includeCipherSuites = new HashSet(Arrays.asList(cipherSuites));
}
@@ -285,7 +414,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStore(String keyStorePath)
{
- checkStarted();
+ checkNotStarted();
_keyStorePath = keyStorePath;
}
@@ -306,7 +435,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStoreProvider(String keyStoreProvider)
{
- checkStarted();
+ checkNotStarted();
_keyStoreProvider = keyStoreProvider;
}
@@ -327,7 +456,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStoreType(String keyStoreType)
{
- checkStarted();
+ checkNotStarted();
_keyStoreType = keyStoreType;
}
@@ -341,7 +470,7 @@ public class SslContextFactory extends AbstractLifeCycle
@Deprecated
public InputStream getKeyStoreInputStream()
{
- checkConfig();
+ checkKeyStore();
return _keyStoreInputStream;
}
@@ -355,7 +484,7 @@ public class SslContextFactory extends AbstractLifeCycle
@Deprecated
public void setKeyStoreInputStream(InputStream keyStoreInputStream)
{
- checkStarted();
+ checkNotStarted();
_keyStoreInputStream = keyStoreInputStream;
}
@@ -376,7 +505,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setCertAlias(String certAlias)
{
- checkStarted();
+ checkNotStarted();
_certAlias = certAlias;
}
@@ -397,7 +526,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStore(String trustStorePath)
{
- checkStarted();
+ checkNotStarted();
_trustStorePath = trustStorePath;
}
@@ -418,7 +547,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStoreProvider(String trustStoreProvider)
{
- checkStarted();
+ checkNotStarted();
_trustStoreProvider = trustStoreProvider;
}
@@ -439,7 +568,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStoreType(String trustStoreType)
{
- checkStarted();
+ checkNotStarted();
_trustStoreType = trustStoreType;
}
@@ -453,7 +582,7 @@ public class SslContextFactory extends AbstractLifeCycle
@Deprecated
public InputStream getTrustStoreInputStream()
{
- checkConfig();
+ checkKeyStore();
return _trustStoreInputStream;
}
@@ -467,7 +596,7 @@ public class SslContextFactory extends AbstractLifeCycle
@Deprecated
public void setTrustStoreInputStream(InputStream trustStoreInputStream)
{
- checkStarted();
+ checkNotStarted();
_trustStoreInputStream = trustStoreInputStream;
}
@@ -490,7 +619,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setNeedClientAuth(boolean needClientAuth)
{
- checkStarted();
+ checkNotStarted();
_needClientAuth = needClientAuth;
}
@@ -513,7 +642,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setWantClientAuth(boolean wantClientAuth)
{
- checkStarted();
+ checkNotStarted();
_wantClientAuth = wantClientAuth;
}
@@ -545,7 +674,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setValidateCerts(boolean validateCerts)
{
- checkStarted();
+ checkNotStarted();
_validateCerts = validateCerts;
}
@@ -566,7 +695,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setValidatePeerCerts(boolean validatePeerCerts)
{
- checkStarted();
+ checkNotStarted();
_validatePeerCerts = validatePeerCerts;
}
@@ -593,7 +722,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setAllowRenegotiate(boolean allowRenegotiate)
{
- checkStarted();
+ checkNotStarted();
_allowRenegotiate = allowRenegotiate;
}
@@ -605,7 +734,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStorePassword(String password)
{
- checkStarted();
+ checkNotStarted();
_keyStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
}
@@ -617,7 +746,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyManagerPassword(String password)
{
- checkStarted();
+ checkNotStarted();
_keyManagerPassword = Password.getPassword(KEYPASSWORD_PROPERTY,password,null);
}
@@ -629,7 +758,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStorePassword(String password)
{
- checkStarted();
+ checkNotStarted();
_trustStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
}
@@ -652,7 +781,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setProvider(String provider)
{
- checkStarted();
+ checkNotStarted();
_sslProvider = provider;
}
@@ -675,7 +804,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setProtocol(String protocol)
{
- checkStarted();
+ checkNotStarted();
_sslProtocol = protocol;
}
@@ -700,7 +829,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setSecureRandomAlgorithm(String algorithm)
{
- checkStarted();
+ checkNotStarted();
_secureRandomAlgorithm = algorithm;
}
@@ -721,7 +850,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setSslKeyManagerFactoryAlgorithm(String algorithm)
{
- checkStarted();
+ checkNotStarted();
_keyManagerFactoryAlgorithm = algorithm;
}
@@ -742,7 +871,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustManagerFactoryAlgorithm(String algorithm)
{
- checkStarted();
+ checkNotStarted();
_trustManagerFactoryAlgorithm = algorithm;
}
@@ -763,7 +892,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setCrlPath(String crlPath)
{
- checkStarted();
+ checkNotStarted();
_crlPath = crlPath;
}
@@ -786,7 +915,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setMaxCertPathLength(int maxCertPathLength)
{
- checkStarted();
+ checkNotStarted();
_maxCertPathLength = maxCertPathLength;
}
@@ -797,6 +926,8 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public SSLContext getSslContext()
{
+ if (!isStarted())
+ throw new IllegalStateException(getState());
return _context;
}
@@ -807,60 +938,11 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setSslContext(SSLContext sslContext)
{
- checkStarted();
+ checkNotStarted();
_context = sslContext;
}
- /* ------------------------------------------------------------ */
- /**
- * @throws Exception
- */
- protected void createSSLContext() throws Exception
- {
- // verify that keystore and truststore
- // parameters are set up correctly
- checkConfig();
-
- KeyStore keyStore = loadKeyStore();
- KeyStore trustStore = loadTrustStore();
-
- Collection extends CRL> crls = loadCRL(_crlPath);
-
- if (_validateCerts && keyStore != null)
- {
- if (_certAlias == null)
- {
- List aliases = Collections.list(keyStore.aliases());
- _certAlias = aliases.size() == 1 ? aliases.get(0) : null;
- }
-
- Certificate cert = _certAlias == null?null:keyStore.getCertificate(_certAlias);
- if (cert == null)
- {
- throw new Exception("No certificate found in the keystore" + (_certAlias==null ? "":" for alias " + _certAlias));
- }
-
- CertificateValidator validator = new CertificateValidator(trustStore, crls);
- validator.setMaxCertPathLength(_maxCertPathLength);
- validator.setEnableCRLDP(_enableCRLDP);
- validator.setEnableOCSP(_enableOCSP);
- validator.setOcspResponderURL(_ocspResponderURL);
- validator.validate(keyStore, cert);
- }
-
- KeyManager[] keyManagers = getKeyManagers(keyStore);
- TrustManager[] trustManagers = getTrustManagers(trustStore,crls);
-
- SecureRandom secureRandom = (_secureRandomAlgorithm == null)?null:SecureRandom.getInstance(_secureRandomAlgorithm);
- _context = (_sslProvider == null)?SSLContext.getInstance(_sslProtocol):SSLContext.getInstance(_sslProtocol,_sslProvider);
- _context.init(keyManagers,trustManagers,secureRandom);
-
- SSLSessionContext sslSessionContext = _context.getServerSessionContext();
- sslSessionContext.setSessionCacheSize(_sslSessionCacheSize);
- sslSessionContext.setSessionTimeout(_sslSessionTimeout);
- }
-
/* ------------------------------------------------------------ */
/**
* Override this method to provide alternate way to load a keystore.
@@ -1014,33 +1096,27 @@ public class SslContextFactory extends AbstractLifeCycle
/* ------------------------------------------------------------ */
/**
- * Check configuration. Ensures that if keystore has been
+ * Check KetyStore Configuration. Ensures that if keystore has been
* configured but there's no truststore, that keystore is
* used as truststore.
- * @return true SslContextFactory configuration can be used in server connector.
+ * @throws IllegalStateException if SslContextFactory configuration can't be used.
*/
- public boolean checkConfig()
+ public void checkKeyStore()
{
- boolean check = true;
if (_keyStore == null && _keyStoreInputStream == null && _keyStorePath == null)
+ throw new IllegalStateException("SSL doesn't have a valid keystore");
+
+ // if the keystore has been configured but there is no
+ // truststore configured, use the keystore as the truststore
+ if (_trustStore == null && _trustStoreInputStream == null && _trustStorePath == null)
{
- // configuration doesn't have a valid keystore
- check = false;
- }
- else
- {
- // if the keystore has been configured but there is no
- // truststore configured, use the keystore as the truststore
- if (_trustStore == null && _trustStoreInputStream == null && _trustStorePath == null)
- {
- _trustStore = _keyStore;
- _trustStorePath = _keyStorePath;
- _trustStoreInputStream = _keyStoreInputStream;
- _trustStoreType = _keyStoreType;
- _trustStoreProvider = _keyStoreProvider;
- _trustStorePassword = _keyStorePassword;
- _trustManagerFactoryAlgorithm = _keyManagerFactoryAlgorithm;
- }
+ _trustStore = _keyStore;
+ _trustStorePath = _keyStorePath;
+ _trustStoreInputStream = _keyStoreInputStream;
+ _trustStoreType = _keyStoreType;
+ _trustStoreProvider = _keyStoreProvider;
+ _trustStorePassword = _keyStorePassword;
+ _trustManagerFactoryAlgorithm = _keyManagerFactoryAlgorithm;
}
// It's the same stream we cannot read it twice, so read it once in memory
@@ -1057,11 +1133,9 @@ public class SslContextFactory extends AbstractLifeCycle
}
catch (Exception ex)
{
- throw new RuntimeException(ex);
+ throw new IllegalStateException(ex);
}
}
-
- return check;
}
/* ------------------------------------------------------------ */
@@ -1073,57 +1147,68 @@ public class SslContextFactory extends AbstractLifeCycle
* @param supportedCipherSuites Array of supported cipher suites
* @return Array of cipher suites to enable
*/
- public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
+ public String[] selectProtocols(String[] enabledProtocols, String[] supportedProtocols)
{
- Set selectedCipherSuites = null;
- if (enabledCipherSuites != null)
+ Set selected_protocols = new HashSet();
+
+ // Set the starting protocols - either from the included or enabled list
+ if (_includeProtocols!=null)
{
- selectedCipherSuites = new HashSet(Arrays.asList(enabledCipherSuites));
+ // Use only the supported included protocols
+ for (String protocol : supportedProtocols)
+ if (_includeProtocols.contains(protocol))
+ selected_protocols.add(protocol);
}
else
+ selected_protocols.addAll(Arrays.asList(enabledProtocols));
+
+
+ // Remove any excluded protocols
+ if (_excludeProtocols != null)
+ selected_protocols.removeAll(_excludeProtocols);
+
+ return selected_protocols.toArray(new String[selected_protocols.size()]);
+ }
+
+ /* ------------------------------------------------------------ */
+ /**
+ * Select cipher suites to be used by the connector
+ * based on configured inclusion and exclusion lists
+ * as well as enabled and supported cipher suite lists.
+ * @param enabledCipherSuites Array of enabled cipher suites
+ * @param supportedCipherSuites Array of supported cipher suites
+ * @return Array of cipher suites to enable
+ */
+ public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
+ {
+ Set selected_ciphers = new HashSet();
+
+ // Set the starting ciphers - either from the included or enabled list
+ if (_includeCipherSuites!=null)
{
- selectedCipherSuites = new HashSet();
+ // Use only the supported included ciphers
+ for (String cipherSuite : supportedCipherSuites)
+ if (_includeCipherSuites.contains(cipherSuite))
+ selected_ciphers.add(cipherSuite);
}
-
- if ((supportedCipherSuites != null && supportedCipherSuites.length > 0) &&
- (_includeCipherSuites != null && _includeCipherSuites.size() > 0))
- {
- Set supportedCSList = new HashSet(Arrays.asList(supportedCipherSuites));
-
- for (String cipherName : _includeCipherSuites)
- {
- if ((!selectedCipherSuites.contains(cipherName)) &&
- supportedCSList.contains(cipherName))
- {
- selectedCipherSuites.add(cipherName);
- }
- }
- }
-
- if (_excludeCipherSuites != null && _excludeCipherSuites.size() > 0)
- {
- for (String cipherName : _excludeCipherSuites)
- {
- if (selectedCipherSuites.contains(cipherName))
- {
- selectedCipherSuites.remove(cipherName);
- }
- }
- }
-
- return selectedCipherSuites.toArray(new String[selectedCipherSuites.size()]);
+ else
+ selected_ciphers.addAll(Arrays.asList(enabledCipherSuites));
+
+
+ // Remove any excluded ciphers
+ if (_excludeCipherSuites != null)
+ selected_ciphers.removeAll(_excludeCipherSuites);
+ return selected_ciphers.toArray(new String[selected_ciphers.size()]);
}
/* ------------------------------------------------------------ */
/**
* Check if the lifecycle has been started and throw runtime exception
*/
- protected void checkStarted()
+ protected void checkNotStarted()
{
if (isStarted())
- {
- throw new IllegalStateException("Cannot modify configuration after SslContextFactory was started");
- }
+ throw new IllegalStateException("Cannot modify configuration when "+getState());
}
/* ------------------------------------------------------------ */
@@ -1141,7 +1226,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setEnableCRLDP(boolean enableCRLDP)
{
- checkStarted();
+ checkNotStarted();
_enableCRLDP = enableCRLDP;
}
@@ -1161,7 +1246,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setEnableOCSP(boolean enableOCSP)
{
- checkStarted();
+ checkNotStarted();
_enableOCSP = enableOCSP;
}
@@ -1181,7 +1266,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setOcspResponderURL(String ocspResponderURL)
{
- checkStarted();
+ checkNotStarted();
_ocspResponderURL = ocspResponderURL;
}
@@ -1192,7 +1277,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStore(KeyStore keyStore)
{
- checkStarted();
+ checkNotStarted();
_keyStore = keyStore;
}
@@ -1203,7 +1288,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStore(KeyStore trustStore)
{
- checkStarted();
+ checkNotStarted();
_trustStore = trustStore;
}
@@ -1214,7 +1299,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setKeyStoreResource(Resource resource)
{
- checkStarted();
+ checkNotStarted();
try
{
@@ -1233,7 +1318,7 @@ public class SslContextFactory extends AbstractLifeCycle
*/
public void setTrustStore(Resource resource)
{
- checkStarted();
+ checkNotStarted();
try
{
@@ -1299,4 +1384,83 @@ public class SslContextFactory extends AbstractLifeCycle
{
_sslSessionTimeout = sslSessionTimeout;
}
+
+
+ /* ------------------------------------------------------------ */
+ public SSLServerSocket newSslServerSocket(String host,int port,int backlog) throws IOException
+ {
+ SSLServerSocketFactory factory = _context.getServerSocketFactory();
+
+ SSLServerSocket socket =
+ (SSLServerSocket) (host==null ?
+ factory.createServerSocket(port,backlog):
+ factory.createServerSocket(port,backlog,InetAddress.getByName(host)));
+
+ if (getWantClientAuth())
+ socket.setWantClientAuth(getWantClientAuth());
+ if (getNeedClientAuth())
+ socket.setNeedClientAuth(getNeedClientAuth());
+
+ socket.setEnabledCipherSuites(selectCipherSuites(
+ socket.getEnabledCipherSuites(),
+ socket.getSupportedCipherSuites()));
+ socket.setEnabledProtocols(selectProtocols(socket.getEnabledProtocols(),socket.getSupportedProtocols()));
+
+ return socket;
+ }
+
+ /* ------------------------------------------------------------ */
+ public SSLSocket newSslSocket() throws IOException
+ {
+ SSLSocketFactory factory = _context.getSocketFactory();
+
+ SSLSocket socket = (SSLSocket)factory.createSocket();
+
+ if (getWantClientAuth())
+ socket.setWantClientAuth(getWantClientAuth());
+ if (getNeedClientAuth())
+ socket.setNeedClientAuth(getNeedClientAuth());
+
+ socket.setEnabledCipherSuites(selectCipherSuites(
+ socket.getEnabledCipherSuites(),
+ socket.getSupportedCipherSuites()));
+ socket.setEnabledProtocols(selectProtocols(socket.getEnabledProtocols(),socket.getSupportedProtocols()));
+
+ return socket;
+ }
+
+ /* ------------------------------------------------------------ */
+ public SSLEngine newSslEngine(String host,int port)
+ {
+ SSLEngine sslEngine=isSessionCachingEnabled()
+ ?_context.createSSLEngine(host, port)
+ :_context.createSSLEngine();
+
+ customize(sslEngine);
+ return sslEngine;
+ }
+
+ /* ------------------------------------------------------------ */
+ public SSLEngine newSslEngine()
+ {
+ SSLEngine sslEngine=_context.createSSLEngine();
+ customize(sslEngine);
+ return sslEngine;
+ }
+
+ /* ------------------------------------------------------------ */
+ public void customize(SSLEngine sslEngine)
+ {
+ if (getWantClientAuth())
+ sslEngine.setWantClientAuth(getWantClientAuth());
+ if (getNeedClientAuth())
+ sslEngine.setNeedClientAuth(getNeedClientAuth());
+
+ sslEngine.setEnabledCipherSuites(selectCipherSuites(
+ sslEngine.getEnabledCipherSuites(),
+ sslEngine.getSupportedCipherSuites()));
+
+ sslEngine.setEnabledProtocols(selectProtocols(sslEngine.getEnabledProtocols(),sslEngine.getSupportedProtocols()));
+ }
+
}
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/ChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/ChannelEndPoint.java
index 839996dbb52..9670613eede 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/ChannelEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/ChannelEndPoint.java
@@ -109,9 +109,12 @@ public class ChannelEndPoint implements EndPoint
if (_channel.isOpen() && _channel instanceof SocketChannel)
{
Socket socket= ((SocketChannel)_channel).socket();
- if (!socket.isClosed()&&!socket.isInputShutdown())
+ if (!socket.isClosed())
{
- socket.shutdownInput();
+ if(socket.isOutputShutdown())
+ socket.close();
+ else if (!socket.isInputShutdown())
+ socket.shutdownInput();
}
}
}
@@ -124,9 +127,12 @@ public class ChannelEndPoint implements EndPoint
if (_channel.isOpen() && _channel instanceof SocketChannel)
{
Socket socket= ((SocketChannel)_channel).socket();
- if (!socket.isClosed()&&!socket.isOutputShutdown())
+ if (!socket.isClosed())
{
- socket.shutdownOutput();
+ if (socket.isInputShutdown())
+ socket.close();
+ else if (!socket.isOutputShutdown())
+ socket.shutdownOutput();
}
}
}
@@ -160,8 +166,8 @@ public class ChannelEndPoint implements EndPoint
{
final NIOBuffer nbuf = (NIOBuffer)buf;
final ByteBuffer bbuf=nbuf.getByteBuffer();
- //noinspection SynchronizationOnLocalVariableOrMethodParameter
+ //noinspection SynchronizationOnLocalVariableOrMethodParameter
try
{
synchronized(bbuf)
@@ -178,13 +184,17 @@ public class ChannelEndPoint implements EndPoint
}
}
- if (len<0 && isOpen() && !isInputShutdown())
+ if (len<0 && isOpen())
{
- shutdownInput();
+ if (!isInputShutdown())
+ shutdownInput();
+ else if (isOutputShutdown())
+ _channel.close();
}
}
catch (IOException x)
{
+ LOG.debug(x);
try
{
close();
@@ -196,7 +206,6 @@ public class ChannelEndPoint implements EndPoint
if (len>0)
throw x;
- LOG.ignore(x);
len=-1;
}
}
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
index fd5413ff3e0..5bf00235e0c 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectChannelEndPoint.java
@@ -34,7 +34,7 @@ import org.eclipse.jetty.util.log.Logger;
*/
public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPoint, ConnectedEndPoint
{
- public static final Logger __log=Log.getLogger("org.eclipse.jetty.io.nio");
+ public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio");
private final SelectorManager.SelectSet _selectSet;
private final SelectorManager _manager;
@@ -54,7 +54,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
private boolean _writeBlocked;
private boolean _open;
private volatile long _idleTimestamp;
-
+
/* ------------------------------------------------------------ */
public SelectChannelEndPoint(SocketChannel channel, SelectSet selectSet, SelectionKey key, int maxIdleTime)
throws IOException
@@ -90,6 +90,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
scheduleIdle();
}
+
/* ------------------------------------------------------------ */
public SelectionKey getSelectionKey()
{
@@ -205,7 +206,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
if(!dispatched)
{
_dispatched = false;
- __log.warn("Dispatched Failed! "+this+" to "+_manager);
+ LOG.warn("Dispatched Failed! "+this+" to "+_manager);
updateKey();
}
}
@@ -250,7 +251,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
public void checkIdleTimestamp(long now)
{
long idleTimestamp=_idleTimestamp;
- if (idleTimestamp!=0 && _maxIdleTime>0 && now>(idleTimestamp+_maxIdleTime))
+ if (!getChannel().isOpen() || idleTimestamp!=0 && _maxIdleTime>0 && now>(idleTimestamp+_maxIdleTime))
idleExpired();
}
@@ -260,6 +261,15 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
_connection.idleExpired();
}
+ /* ------------------------------------------------------------ */
+ /**
+ * @return True if the endpoint has produced/consumed bytes itself (non application data).
+ */
+ public boolean isProgressing()
+ {
+ return false;
+ }
+
/* ------------------------------------------------------------ */
/*
*/
@@ -340,7 +350,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
catch (InterruptedException e)
{
- __log.warn(e);
+ LOG.warn(e);
}
finally
{
@@ -385,7 +395,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
catch (InterruptedException e)
{
- __log.warn(e);
+ LOG.warn(e);
}
finally
{
@@ -398,7 +408,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
catch(Throwable e)
{
// TODO remove this if it finds nothing
- __log.warn(e);
+ LOG.warn(e);
if (e instanceof RuntimeException)
throw (RuntimeException)e;
if (e instanceof Error)
@@ -414,10 +424,20 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
return true;
}
+
+ /* ------------------------------------------------------------ */
+ /* short cut for busyselectChannelServerTest */
+ public void clearWritable()
+ {
+ _writable=false;
+ }
/* ------------------------------------------------------------ */
public void scheduleWrite()
{
+ if (_writable==true)
+ LOG.debug("Required scheduleWrite {}",this);
+
_writable=false;
updateKey();
}
@@ -445,7 +465,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
catch(Exception e)
{
_key=null;
- __log.ignore(e);
+ LOG.ignore(e);
}
}
@@ -483,7 +503,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
catch (Exception e)
{
- __log.ignore(e);
+ LOG.ignore(e);
if (_key!=null && _key.isValid())
{
_key.cancel();
@@ -520,9 +540,9 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
cancelIdle();
if (_open)
{
+ _open=false;
_selectSet.destroyEndPoint(this);
}
- _open=false;
_key = null;
}
}
@@ -545,7 +565,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
final Connection next = _connection.handle();
if (next!=_connection)
{
- __log.debug("{} replaced {}",next,_connection);
+ LOG.debug("{} replaced {}",next,_connection);
_connection=next;
continue;
}
@@ -554,26 +574,26 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
catch (ClosedChannelException e)
{
- __log.ignore(e);
+ LOG.ignore(e);
}
catch (EofException e)
{
- __log.debug("EOF", e);
- try{close();}
- catch(IOException e2){__log.ignore(e2);}
+ LOG.debug("EOF", e);
+ try{getChannel().close();}
+ catch(IOException e2){LOG.ignore(e2);}
}
catch (IOException e)
{
- __log.warn(e.toString());
- __log.debug(e);
- try{close();}
- catch(IOException e2){__log.ignore(e2);}
+ LOG.warn(e.toString());
+ LOG.debug(e);
+ try{getChannel().close();}
+ catch(IOException e2){LOG.ignore(e2);}
}
catch (Throwable e)
{
- __log.warn("handle failed", e);
- try{close();}
- catch(IOException e2){__log.ignore(e2);}
+ LOG.warn("handle failed", e);
+ try{getChannel().close();}
+ catch(IOException e2){LOG.ignore(e2);}
}
dispatched=!undispatch();
}
@@ -585,7 +605,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
dispatched=!undispatch();
while (dispatched)
{
- __log.warn("SCEP.run() finally DISPATCHED");
+ LOG.warn("SCEP.run() finally DISPATCHED");
dispatched=!undispatch();
}
}
@@ -605,7 +625,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
}
catch (IOException e)
{
- __log.ignore(e);
+ LOG.ignore(e);
}
finally
{
@@ -620,7 +640,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements AsyncEndPo
synchronized(this)
{
return "SCEP@" + hashCode() + _channel+
- "[d=" + _dispatched + ",io=" + _interestOps+
+ "[o="+isOpen()+" d=" + _dispatched + ",io=" + _interestOps+
",w=" + _writable + ",rb=" + _readBlocked + ",wb=" + _writeBlocked + "]";
}
}
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectorManager.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectorManager.java
index 5b80a68d9df..1b8218832a4 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectorManager.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SelectorManager.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.io.nio;
@@ -30,7 +30,6 @@ import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
-
import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
@@ -49,21 +48,16 @@ import org.eclipse.jetty.util.thread.Timeout.Task;
* The Selector Manager manages and number of SelectSets to allow
* NIO scheduling to scale to large numbers of connections.
*
- * This class works around a number of know JVM bugs. For details
- * see http://wiki.eclipse.org/Jetty/Feature/JVM_NIO_Bug
*/
public abstract class SelectorManager extends AbstractLifeCycle implements Dumpable
{
public static final Logger LOG=Log.getLogger("org.eclipse.jetty.io.nio");
-
- // TODO Tune these by approx system speed.
- private static final int __JVMBUG_THRESHHOLD=Integer.getInteger("org.eclipse.jetty.io.nio.JVMBUG_THRESHHOLD",0).intValue();
+
private static final int __MONITOR_PERIOD=Integer.getInteger("org.eclipse.jetty.io.nio.MONITOR_PERIOD",1000).intValue();
private static final int __MAX_SELECTS=Integer.getInteger("org.eclipse.jetty.io.nio.MAX_SELECTS",25000).intValue();
private static final int __BUSY_PAUSE=Integer.getInteger("org.eclipse.jetty.io.nio.BUSY_PAUSE",50).intValue();
- private static final int __BUSY_KEY=Integer.getInteger("org.eclipse.jetty.io.nio.BUSY_KEY",-1).intValue();
private static final int __IDLE_TICK=Integer.getInteger("org.eclipse.jetty.io.nio.IDLE_TICK",400).intValue();
-
+
private int _maxIdleTime;
private int _lowResourcesMaxIdleTime;
private long _lowResourcesConnections;
@@ -72,7 +66,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
private volatile int _set;
private boolean _deferringInterestedOps0=true;
private int _selectorPriorityDelta=0;
-
+
/* ------------------------------------------------------------ */
/**
* @param maxIdleTime The maximum period in milli seconds that a connection may be idle before it is closed.
@@ -82,18 +76,18 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
_maxIdleTime=(int)maxIdleTime;
}
-
+
/* ------------------------------------------------------------ */
/**
* @param selectSets number of select sets to create
*/
public void setSelectSets(int selectSets)
{
- long lrc = _lowResourcesConnections * _selectSets;
+ long lrc = _lowResourcesConnections * _selectSets;
_selectSets=selectSets;
_lowResourcesConnections=lrc/_selectSets;
}
-
+
/* ------------------------------------------------------------ */
/**
* @return the max idle time
@@ -102,7 +96,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
return _maxIdleTime;
}
-
+
/* ------------------------------------------------------------ */
/**
* @return the number of select sets in use
@@ -114,14 +108,14 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
/* ------------------------------------------------------------ */
/**
- * @param i
+ * @param i
* @return The select set
*/
public SelectSet getSelectSet(int i)
{
return _selectSet[i];
}
-
+
/* ------------------------------------------------------------ */
/** Register a channel
* @param channel
@@ -132,8 +126,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// The ++ increment here is not atomic, but it does not matter.
// so long as the value changes sometimes, then connections will
// be distributed over the available sets.
-
- int s=_set++;
+
+ int s=_set++;
s=s%_selectSets;
SelectSet[] sets=_selectSet;
if (sets!=null)
@@ -144,7 +138,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
}
}
-
+
/* ------------------------------------------------------------ */
/** Register a channel
* @param channel
@@ -154,8 +148,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
// The ++ increment here is not atomic, but it does not matter.
// so long as the value changes sometimes, then connections will
// be distributed over the available sets.
-
- int s=_set++;
+
+ int s=_set++;
s=s%_selectSets;
SelectSet[] sets=_selectSet;
if (sets!=null)
@@ -165,14 +159,14 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
set.wakeup();
}
}
-
+
/* ------------------------------------------------------------ */
/** Register a {@link ServerSocketChannel}
* @param acceptChannel
*/
public void register(ServerSocketChannel acceptChannel)
{
- int s=_set++;
+ int s=_set++;
s=s%_selectSets;
SelectSet set=_selectSet[s];
set.addChange(acceptChannel);
@@ -196,8 +190,8 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
_selectorPriorityDelta=delta;
}
-
-
+
+
/* ------------------------------------------------------------ */
/**
* @return the lowResourcesConnections
@@ -237,7 +231,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
{
_lowResourcesMaxIdleTime=(int)lowResourcesMaxIdleTime;
}
-
+
/* ------------------------------------------------------------------------------- */
public abstract boolean dispatch(Runnable task);
@@ -254,7 +248,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_selectSet[i]= new SelectSet(i);
super.doStart();
-
+
// start a thread to Select
for (int i=0;i _changes = new ConcurrentLinkedQueue