diff options
Diffstat (limited to 'jetty-client/src/main/java/org/eclipse/jetty')
9 files changed, 172 insertions, 66 deletions
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/CachedExchange.java b/jetty-client/src/main/java/org/eclipse/jetty/client/CachedExchange.java index de1e9933dd..c36cb6834d 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/CachedExchange.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/CachedExchange.java @@ -35,14 +35,14 @@ public class CachedExchange extends HttpExchange _responseFields = cacheHeaders ? new HttpFields() : null; } - public int getResponseStatus() + public synchronized int getResponseStatus() { if (getStatus() < HttpExchange.STATUS_PARSING_HEADERS) throw new IllegalStateException("Response not received yet"); return _responseStatus; } - public HttpFields getResponseFields() + public synchronized HttpFields getResponseFields() { if (getStatus() < HttpExchange.STATUS_PARSING_CONTENT) throw new IllegalStateException("Headers not completely received yet"); @@ -50,14 +50,14 @@ public class CachedExchange extends HttpExchange } @Override - protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException + protected synchronized void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { _responseStatus = status; super.onResponseStatus(version, status, reason); } @Override - protected void onResponseHeader(Buffer name, Buffer value) throws IOException + protected synchronized void onResponseHeader(Buffer name, Buffer value) throws IOException { if (_responseFields != null) _responseFields.add(name, value); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/ContentExchange.java b/jetty-client/src/main/java/org/eclipse/jetty/client/ContentExchange.java index 2e0b3411f4..5673cef584 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/ContentExchange.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/ContentExchange.java @@ -45,14 +45,14 @@ public class ContentExchange extends CachedExchange super(cacheFields); } - public String getResponseContent() throws UnsupportedEncodingException + public synchronized String getResponseContent() throws UnsupportedEncodingException { if (_responseContent != null) return _responseContent.toString(_encoding); return null; } - public byte[] getResponseContentBytes() + public synchronized byte[] getResponseContentBytes() { if (_responseContent != null) return _responseContent.toByteArray(); @@ -60,7 +60,7 @@ public class ContentExchange extends CachedExchange } @Override - protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException + protected synchronized void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { if (_responseContent!=null) _responseContent.reset(); @@ -68,7 +68,7 @@ public class ContentExchange extends CachedExchange } @Override - protected void onResponseHeader(Buffer name, Buffer value) throws IOException + protected synchronized void onResponseHeader(Buffer name, Buffer value) throws IOException { super.onResponseHeader(name, value); int header = HttpHeaders.CACHE.getOrdinal(name); @@ -92,7 +92,7 @@ public class ContentExchange extends CachedExchange } @Override - protected void onResponseContent(Buffer content) throws IOException + protected synchronized void onResponseContent(Buffer content) throws IOException { super.onResponseContent(content); if (_responseContent == null) @@ -101,7 +101,7 @@ public class ContentExchange extends CachedExchange } @Override - protected void onRetry() throws IOException + protected synchronized void onRetry() throws IOException { if (_fileForUpload != null) { @@ -112,17 +112,17 @@ public class ContentExchange extends CachedExchange super.onRetry(); } - private InputStream getInputStream() throws IOException + private synchronized InputStream getInputStream() throws IOException { return new FileInputStream(_fileForUpload); } - public File getFileForUpload() + public synchronized File getFileForUpload() { return _fileForUpload; } - public void setFileForUpload(File fileForUpload) throws IOException + public synchronized void setFileForUpload(File fileForUpload) throws IOException { this._fileForUpload = fileForUpload; setRequestContentSource(getInputStream()); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java index 0ee716cf16..be20cc49c6 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java @@ -75,11 +75,8 @@ import org.eclipse.jetty.util.thread.Timeout; * be allocated from a destination, so that multiple request sources are not multiplexed * over the same connection. * - * - * - * - * @see {@link HttpExchange} - * @see {@link HttpDestination} + * @see HttpExchange + * @see HttpDestination */ public class HttpClient extends HttpBuffers implements Attributes { @@ -212,10 +209,6 @@ public class HttpClient extends HttpBuffers implements Attributes } /* ------------------------------------------------------------ */ - /** - * @param name - * @return - */ public void clearAttributes() { _attributes.clearAttributes(); @@ -287,7 +280,7 @@ public class HttpClient extends HttpBuffers implements Attributes /** * returns the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null * - * @return + * @return the SecurityRealmResolver reg_realmResolveristered with the HttpClient or null */ public RealmResolver getRealmResolver() { @@ -303,7 +296,7 @@ public class HttpClient extends HttpBuffers implements Attributes /** * Registers a listener that can listen to the stream of execution between the client and the - * server and influence events. Sequential calls to the method wrapper sequentially wrap the preceeding + * server and influence events. Sequential calls to the method wrapper sequentially wrap the preceding * listener in a delegation model. * <p/> * NOTE: the SecurityListener is a special listener which doesn't need to be added via this @@ -320,7 +313,8 @@ public class HttpClient extends HttpBuffers implements Attributes } _registeredListeners.add(listenerClass); } - + + /* ------------------------------------------------------------ */ public LinkedList<String> getRegisteredListeners() { return _registeredListeners; @@ -528,7 +522,7 @@ public class HttpClient extends HttpBuffers implements Attributes * if a keystore location has been provided then client will attempt to use it as the keystore, * otherwise we simply ignore certificates and run with a loose ssl context. * - * @return + * @return the SSL context * @throws IOException */ protected SSLContext getSSLContext() throws IOException @@ -807,12 +801,36 @@ public class HttpClient extends HttpBuffers implements Attributes /* ------------------------------------------------------------ */ public void setKeyManagerPassword(String keyManagerPassword) { - this._keyManagerPassword = new Password(keyManagerPassword).toString();; + this._keyManagerPassword = new Password(keyManagerPassword).toString(); } /* ------------------------------------------------------------ */ public void setTrustStorePassword(String trustStorePassword) { - this._trustStorePassword = new Password(trustStorePassword).toString();; + this._trustStorePassword = new Password(trustStorePassword).toString(); + } + + /* ------------------------------------------------------------ */ + public String getKeyStoreType() + { + return this._keyStoreType; + } + + /* ------------------------------------------------------------ */ + public void setKeyStoreType(String keyStoreType) + { + this._keyStoreType = keyStoreType; + } + + /* ------------------------------------------------------------ */ + public String getTrustStoreType() + { + return this._trustStoreType; + } + + /* ------------------------------------------------------------ */ + public void setTrustStoreType(String trustStoreType) + { + this._trustStoreType = trustStoreType; } } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java index 9633c7e9ec..9244314355 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java @@ -13,6 +13,7 @@ package org.eclipse.jetty.client; +import java.io.EOFException; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; @@ -28,7 +29,6 @@ import org.eclipse.jetty.http.HttpParser; import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpVersions; -import org.eclipse.jetty.http.ssl.SslSelectChannelEndPoint; import org.eclipse.jetty.io.AsyncEndPoint; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; @@ -37,6 +37,7 @@ import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.View; import org.eclipse.jetty.io.nio.SelectChannelEndPoint; +import org.eclipse.jetty.io.nio.SslSelectChannelEndPoint; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.thread.Timeout; @@ -214,23 +215,28 @@ public class HttpConnection implements Connection if (!_generator.isComplete()) { - InputStream in = _exchange.getRequestContentSource(); - if (in != null) + if (_exchange!=null) { - if (_requestContentChunk == null || _requestContentChunk.length() == 0) + InputStream in = _exchange.getRequestContentSource(); + if (in != null) { - _requestContentChunk = _exchange.getRequestContentChunk(); - _destination.getHttpClient().schedule(_timeout); + if (_requestContentChunk == null || _requestContentChunk.length() == 0) + { + _requestContentChunk = _exchange.getRequestContentChunk(); + _destination.getHttpClient().schedule(_timeout); - if (_requestContentChunk != null) - _generator.addContent(_requestContentChunk,false); - else - _generator.complete(); + if (_requestContentChunk != null) + _generator.addContent(_requestContentChunk,false); + else + _generator.complete(); - flushed = _generator.flushBuffer(); - io += flushed; + flushed = _generator.flushBuffer(); + io += flushed; + } } - } + else + _generator.complete(); + } else _generator.complete(); } @@ -333,16 +339,17 @@ public class HttpConnection implements Connection no_progress = 0; if (_exchange != null) { + HttpExchange exchange=_exchange; _exchange.disassociate(); _exchange = null; if (_status==HttpStatus.SWITCHING_PROTOCOLS_101) { - HttpConnection switched=_exchange.onSwitchProtocol(_endp); + Connection switched=exchange.onSwitchProtocol(_endp); if (switched!=null) { // switched protocol! - HttpExchange exchange = _pipeline; + exchange = _pipeline; _pipeline = null; if (exchange!=null) _destination.send(exchange); @@ -351,7 +358,6 @@ public class HttpConnection implements Connection } } - if (_pipeline == null) { if (!isReserved()) @@ -364,13 +370,13 @@ public class HttpConnection implements Connection if (!isReserved()) _destination.returnConnection(this,close); - HttpExchange exchange = _pipeline; + exchange = _pipeline; _pipeline = null; _destination.send(exchange); } else { - HttpExchange exchange = _pipeline; + exchange = _pipeline; _pipeline = null; send(exchange); } @@ -388,6 +394,11 @@ public class HttpConnection implements Connection { _exchange.disassociate(); } + + if (!_generator.isComplete() && _generator.getBytesBuffered()>0 && _endp instanceof AsyncEndPoint) + { + ((AsyncEndPoint)_endp).setWritable(false); + } } return this; @@ -544,6 +555,8 @@ public class HttpConnection implements Connection @Override public void headerComplete() throws IOException { + if (_endp instanceof AsyncEndPoint) + ((AsyncEndPoint)_endp).scheduleIdle(); HttpExchange exchange = _exchange; if (exchange!=null) exchange.setStatus(HttpExchange.STATUS_PARSING_CONTENT); @@ -552,6 +565,8 @@ public class HttpConnection implements Connection @Override public void content(Buffer ref) throws IOException { + if (_endp instanceof AsyncEndPoint) + ((AsyncEndPoint)_endp).scheduleIdle(); HttpExchange exchange = _exchange; if (exchange!=null) exchange.getEventListener().onResponseContent(ref); @@ -579,6 +594,25 @@ public class HttpConnection implements Connection public void close() throws IOException { + //if there is a live, unfinished exchange, set its status to be + //excepted and wake up anyone waiting on waitForDone() + + if (_exchange != null && !_exchange.isDone()) + { + switch (_exchange.getStatus()) + { + case HttpExchange.STATUS_CANCELLED: + case HttpExchange.STATUS_CANCELLING: + case HttpExchange.STATUS_COMPLETED: + case HttpExchange.STATUS_EXCEPTED: + case HttpExchange.STATUS_EXPIRED: + break; + default: + _exchange.setStatus(HttpExchange.STATUS_EXCEPTED); + _exchange.getEventListener().onException(new EOFException("local close")); + } + } + _endp.close(); } diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java index 09ab59e94d..b885828022 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java @@ -219,7 +219,7 @@ public class HttpDestination if (connection!=null) { _connections.remove(connection); - connection.getEndPoint().close(); + connection.close(); connection=null; } if (_idle.size() > 0) @@ -229,9 +229,10 @@ public class HttpDestination if (connection==null) return null; - if (connection.cancelIdleTimeout() ) + // Check if the connection was idle, + // but it expired just a moment ago + if (connection.cancelIdleTimeout()) return connection; - } } @@ -271,6 +272,11 @@ public class HttpDestination HttpExchange ex = _queue.removeFirst(); ex.setStatus(HttpExchange.STATUS_EXCEPTED); ex.getEventListener().onConnectionFailed(throwable); + + // Since an existing connection had failed, we need to create a + // connection if the queue is not empty and client is running. + if (!_queue.isEmpty() && _client.isStarted()) + startNewConnection(); } } @@ -323,7 +329,7 @@ public class HttpDestination else { HttpExchange ex = _queue.removeFirst(); - connection.send(ex); + send(connection, ex); } } @@ -372,7 +378,7 @@ public class HttpDestination else { HttpExchange ex = _queue.removeFirst(); - connection.send(ex); + send(connection, ex); } this.notifyAll(); } @@ -388,7 +394,7 @@ public class HttpDestination } } - public void returnIdleConnection(HttpConnection connection) throws IOException + public void returnIdleConnection(HttpConnection connection) { try { @@ -403,10 +409,10 @@ public class HttpDestination { _idle.remove(connection); _connections.remove(connection); + if (!_queue.isEmpty() && _client.isStarted()) startNewConnection(); } - } public void send(HttpExchange ex) throws IOException @@ -483,11 +489,9 @@ public class HttpDestination HttpConnection connection = getIdleConnection(); if (connection != null) { - boolean sent = connection.send(ex); - if (!sent) connection = null; + send(connection, ex); } - - if (connection == null) + else { synchronized (this) { @@ -500,6 +504,20 @@ public class HttpDestination } } + protected void send(HttpConnection connection, HttpExchange exchange) throws IOException + { + synchronized (this) + { + // If server closes the connection, put the exchange back + // to the exchange queue and recycle the connection + if(!connection.send(exchange)) + { + _queue.addFirst(exchange); + returnIdleConnection(connection); + } + } + } + @Override public synchronized String toString() { diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java index eae8542cdc..cfe9b81051 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpExchange.java @@ -25,6 +25,7 @@ import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.http.HttpURI; import org.eclipse.jetty.http.HttpVersions; import org.eclipse.jetty.io.Buffer; +import org.eclipse.jetty.io.Connection; import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.BufferCache.CachedBuffer; import org.eclipse.jetty.io.ByteArrayBuffer; @@ -53,8 +54,8 @@ import org.eclipse.jetty.util.log.Log; * see {@link org.eclipse.jetty.client.ContentExchange} and {@link org.eclipse.jetty.client.CachedExchange}.</p> * * <p>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). + * 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).</p> * @@ -129,7 +130,7 @@ public class HttpExchange * || onExpire * || onRequestComplete && onResponseComplete * </pre> - * @return + * @return the done status * @throws InterruptedException */ public int waitForDone () throws InterruptedException @@ -172,6 +173,7 @@ public class HttpExchange case STATUS_WAITING_FOR_CONNECTION: case STATUS_WAITING_FOR_COMMIT: case STATUS_CANCELLING: + case STATUS_EXCEPTED: set=_status.compareAndSet(oldStatus,newStatus); break; } @@ -282,6 +284,7 @@ public class HttpExchange case STATUS_CANCELLING: switch (newStatus) { + case STATUS_EXCEPTED: case STATUS_CANCELLED: if (set=_status.compareAndSet(oldStatus,newStatus)) done(); @@ -300,6 +303,9 @@ public class HttpExchange case STATUS_START: set=_status.compareAndSet(oldStatus,newStatus); break; + default: + set=true; + break; } break; default: @@ -324,6 +330,15 @@ public class HttpExchange } } + /** + * @deprecated + */ + @Deprecated + public boolean isDone (int status) + { + return isDone(); + } + public HttpEventListener getEventListener() { return _listener; @@ -659,7 +674,7 @@ public class HttpExchange /** */ - protected HttpConnection onSwitchProtocol(EndPoint enpd) throws IOException + protected Connection onSwitchProtocol(EndPoint endp) throws IOException { return null; } 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 6e0d47d0a2..d3de1e680a 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 @@ -16,6 +16,7 @@ package org.eclipse.jetty.client; import java.io.IOException; import org.eclipse.jetty.http.HttpHeaders; +import org.eclipse.jetty.http.HttpSchemes; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.io.Buffer; @@ -26,8 +27,8 @@ import org.eclipse.jetty.io.Buffer; */ public class RedirectListener extends HttpEventListenerWrapper { + private final HttpExchange _exchange; private HttpDestination _destination; - private HttpExchange _exchange; private String _location; private int _attempts; private boolean _requestComplete; @@ -44,6 +45,7 @@ public class RedirectListener extends HttpEventListenerWrapper _exchange = ex; } + @Override public void onResponseStatus( Buffer version, int status, Buffer reason ) throws IOException { @@ -61,6 +63,7 @@ public class RedirectListener extends HttpEventListenerWrapper } + @Override public void onResponseHeader( Buffer name, Buffer value ) throws IOException { @@ -77,6 +80,7 @@ public class RedirectListener extends HttpEventListenerWrapper super.onResponseHeader(name,value); } + @Override public void onRequestComplete() throws IOException { _requestComplete = true; @@ -87,6 +91,7 @@ public class RedirectListener extends HttpEventListenerWrapper } } + @Override public void onResponseComplete() throws IOException { _responseComplete = true; @@ -109,7 +114,23 @@ public class RedirectListener extends HttpEventListenerWrapper else _exchange.setURI(_location); - _destination.resend(_exchange); + // destination may have changed + HttpDestination destination=_destination.getHttpClient().getDestination(_exchange.getAddress(),HttpSchemes.HTTPS.equals(String.valueOf(_exchange.getScheme()))); + + 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); + destination.send(_exchange); + } return false; } 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 aba10d0615..730a53a01a 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 @@ -25,7 +25,6 @@ import javax.net.ssl.SSLSession; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.http.HttpVersions; -import org.eclipse.jetty.http.ssl.SslSelectChannelEndPoint; import org.eclipse.jetty.io.Buffer; import org.eclipse.jetty.io.Buffers; import org.eclipse.jetty.io.ConnectedEndPoint; @@ -35,6 +34,7 @@ import org.eclipse.jetty.io.nio.DirectNIOBuffer; import org.eclipse.jetty.io.nio.IndirectNIOBuffer; import org.eclipse.jetty.io.nio.SelectChannelEndPoint; import org.eclipse.jetty.io.nio.SelectorManager; +import org.eclipse.jetty.io.nio.SslSelectChannelEndPoint; import org.eclipse.jetty.util.component.AbstractLifeCycle; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.thread.Timeout; diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/security/SecurityListener.java b/jetty-client/src/main/java/org/eclipse/jetty/client/security/SecurityListener.java index 87d37b9a7a..20902d4312 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/security/SecurityListener.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/security/SecurityListener.java @@ -58,7 +58,7 @@ public class SecurityListener extends HttpEventListenerWrapper * scrapes an authentication type from the authString * * @param authString - * @return + * @return the authentication type */ protected String scrapeAuthenticationType( String authString ) { @@ -80,7 +80,7 @@ public class SecurityListener extends HttpEventListenerWrapper * scrapes a set of authentication details from the authString * * @param authString - * @return + * @return the authentication details */ protected Map<String, String> scrapeAuthenticationDetails( String authString ) { |