Merge branch 'master' into release

This commit is contained in:
Greg Wilkins 2011-11-29 13:03:23 +11:00
commit a420df6bf1
369 changed files with 12202 additions and 7108 deletions

2
.gitignore vendored
View File

@ -20,7 +20,7 @@ target/
.idea/
# Mac filesystem dust
/.DS_Store
.DS_Store
# pmd
.pmdruleset

View File

@ -1,4 +1,4 @@
jetty-7.5.5-SNAPSHOT
jetty-7.6.5-SNAPSHOT
jetty-7.5.4.v20111024 - 24 October 2011
+ 358263 JDBCSessionIdManager add setDatasource(DataSource) method
@ -20,7 +20,7 @@ jetty-7.5.3.v20111011 - 11 October 2011
+ 358649 StdErrLog system properties for package/class logging LEVEL.
jetty-7.5.2.v20111006 - 06 October 2011
+ 336443 add missing comma in DigestAuthenticator string
+ 336443 check nonce count is increasing
+ 342161 ScannerTest fails intermittently on Mac OS X
+ 346419 testing HttpClient FDs
+ 353267 Request._parameters initialization bug

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.5.5-SNAPSHOT</version>
<version>7.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>example-jetty-embedded</artifactId>

View File

@ -15,11 +15,9 @@ package org.eclipse.jetty.embedded;
import java.lang.management.ManagementFactory;
import org.eclipse.jetty.ajp.Ajp13SocketConnector;
import org.eclipse.jetty.deploy.DeploymentManager;
import org.eclipse.jetty.deploy.providers.ContextProvider;
import org.eclipse.jetty.deploy.providers.WebAppProvider;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.jmx.MBeanContainer;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.server.Connector;
@ -35,6 +33,7 @@ import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
public class LikeJettyXml
@ -52,12 +51,12 @@ public class LikeJettyXml
MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
server.getContainer().addEventListener(mbContainer);
server.addBean(mbContainer);
mbContainer.addBean(Log.getLog());
mbContainer.addBean(Log.getRootLogger());
// Setup Threadpool
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(100);
threadPool.setMaxThreads(500);
server.setThreadPool(threadPool);
// Setup Connectors
@ -65,7 +64,7 @@ public class LikeJettyXml
connector.setPort(8080);
connector.setMaxIdleTime(30000);
connector.setConfidentialPort(8443);
connector.setStatsOn(true);
connector.setStatsOn(false);
server.setConnectors(new Connector[]
{ connector });
@ -88,19 +87,25 @@ public class LikeJettyXml
"SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA",
"SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA"
});
cf.setProtocol("TLSv1.1");
cf.addExcludeProtocols(new String[]{"TLSv1","SSLv3"});
ssl_connector.setStatsOn(true);
ssl_connector.setStatsOn(false);
server.addConnector(ssl_connector);
ssl_connector.open();
SslSocketConnector ssl2_connector = new SslSocketConnector(cf);
ssl2_connector.setPort(8444);
ssl2_connector.setStatsOn(false);
server.addConnector(ssl2_connector);
ssl2_connector.open();
/*
Ajp13SocketConnector ajp = new Ajp13SocketConnector();
ajp.setPort(8009);
server.addConnector(ajp);
*/
HandlerCollection handlers = new HandlerCollection();
ContextHandlerCollection contexts = new ContextHandlerCollection();
RequestLogHandler requestLogHandler = new RequestLogHandler();
@ -148,5 +153,4 @@ public class LikeJettyXml
server.join();
}
}

View File

@ -13,11 +13,11 @@
package org.eclipse.jetty.embedded;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
/* ------------------------------------------------------------ */

View File

@ -17,13 +17,13 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
import org.eclipse.jetty.security.LoginService;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.security.Constraint;
public class SecuredHelloHandler
{

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.5.5-SNAPSHOT</version>
<version>7.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-all-server</artifactId>
@ -145,12 +145,6 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.5.5-SNAPSHOT</version>
<version>7.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-all</artifactId>
@ -129,12 +129,6 @@
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.5.5-SNAPSHOT</version>
<version>7.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-client</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.5.5-SNAPSHOT</version>
<version>7.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.5.5-SNAPSHOT</version>
<version>7.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.5.5-SNAPSHOT</version>
<version>7.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.5.5-SNAPSHOT</version>
<version>7.6.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-webapp</artifactId>
@ -95,11 +95,5 @@
<artifactId>servlet-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
</dependency>
</dependencies>
</project>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.5.5-SNAPSHOT</version>
<version>7.6.0-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>

View File

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

View File

@ -216,7 +216,10 @@ public class Ajp13Connection extends BlockingHttpConnection
public void parsedRequestAttribute(String key, Buffer value) throws IOException
{
_request.setAttribute(key, value.toString());
if (value==null)
_request.removeAttribute(key);
else
_request.setAttribute(key,value.toString());
}
public void parsedRequestAttribute(String key, int value) throws IOException

View File

@ -133,9 +133,9 @@ public class Ajp13Generator extends AbstractGenerator
/* ------------------------------------------------------------ */
@Override
public void reset(boolean returnBuffers)
public void reset()
{
super.reset(returnBuffers);
super.reset();
_needEOC = false;
_needMore = false;
@ -487,7 +487,7 @@ public class Ajp13Generator extends AbstractGenerator
/* ------------------------------------------------------------ */
@Override
public long flushBuffer() throws IOException
public int flushBuffer() throws IOException
{
try
{
@ -819,7 +819,7 @@ public class Ajp13Generator extends AbstractGenerator
while (buff.length() > 0);
_buffers.returnBuffer(buff);
reset(true);
reset();
}

View File

@ -148,21 +148,16 @@ public class Ajp13Parser implements Parser
}
/* ------------------------------------------------------------------------------- */
public int parseAvailable() throws IOException
public boolean parseAvailable() throws IOException
{
int len = parseNext();
int total = len > 0 ? len : 0;
boolean progress=parseNext()>0;
// continue parsing
while (!isComplete() && _buffer != null && _buffer.length() > 0)
while (!isComplete() && _buffer!=null && _buffer.length()>0)
{
len = parseNext();
if (len > 0)
total += len;
else
break;
progress |= parseNext()>0;
}
return total;
return progress;
}
/* ------------------------------------------------------------------------------- */
@ -876,6 +871,15 @@ public class Ajp13Parser implements Parser
return _content.length() > 0;
}
}
public boolean isPersistent()
{
return true;
}
public void setPersistent(boolean persistent)
{
LOG.warn("AJP13.setPersistent is not IMPLEMENTED!");
}
}

View File

@ -13,7 +13,7 @@
package org.eclipse.jetty.ajp;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Request;
public class Ajp13Request extends Request
@ -24,7 +24,7 @@ public class Ajp13Request extends Request
protected boolean _sslSecure;
/* ------------------------------------------------------------ */
public Ajp13Request(HttpConnection connection)
public Ajp13Request(AbstractHttpConnection connection)
{
super(connection);
}

View File

@ -13,10 +13,10 @@
package org.eclipse.jetty.ajp;
import java.io.BufferedReader;
import static org.junit.Assert.assertTrue;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;
import java.net.SocketTimeoutException;
@ -39,8 +39,6 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertTrue;
public class Ajp13ConnectionTest
{
private static final Logger LOG = Log.getLogger(Ajp13ConnectionTest.class);

View File

@ -13,6 +13,9 @@
package org.eclipse.jetty.ajp;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import org.eclipse.jetty.io.Buffer;
@ -23,9 +26,6 @@ import org.eclipse.jetty.io.SimpleBuffers;
import org.eclipse.jetty.util.TypeUtil;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class TestAjpParser
{
@Test

View File

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

View File

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

View File

@ -1,5 +1,5 @@
// ========================================================================
// Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
// Copyright (c) 2006-2011 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
@ -13,10 +13,8 @@
package org.eclipse.jetty.client;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.util.Collections;
import java.util.concurrent.atomic.AtomicBoolean;
@ -31,7 +29,6 @@ import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpVersions;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.ByteArrayBuffer;
@ -39,7 +36,6 @@ import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.View;
import org.eclipse.jetty.io.nio.SslSelectChannelEndPoint;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
@ -50,28 +46,26 @@ import org.eclipse.jetty.util.thread.Timeout;
*
* @version $Revision: 879 $ $Date: 2009-09-11 16:13:28 +0200 (Fri, 11 Sep 2009) $
*/
public class HttpConnection extends AbstractConnection implements Dumpable
public abstract class AbstractHttpConnection extends AbstractConnection implements Dumpable
{
private static final Logger LOG = Log.getLogger(HttpConnection.class);
private static final Logger LOG = Log.getLogger(AbstractHttpConnection.class);
private HttpDestination _destination;
private HttpGenerator _generator;
private HttpParser _parser;
private boolean _http11 = true;
private int _status;
private Buffer _connectionHeader;
private Buffer _requestContentChunk;
private boolean _requestComplete;
private boolean _reserved;
protected HttpDestination _destination;
protected HttpGenerator _generator;
protected HttpParser _parser;
protected boolean _http11 = true;
protected int _status;
protected Buffer _connectionHeader;
protected boolean _reserved;
// The current exchange waiting for a response
private volatile HttpExchange _exchange;
private HttpExchange _pipeline;
protected volatile HttpExchange _exchange;
protected HttpExchange _pipeline;
private final Timeout.Task _idleTimeout = new ConnectionIdleTask();
private AtomicBoolean _idle = new AtomicBoolean(false);
HttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endp)
AbstractHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endp)
{
super(endp);
@ -101,6 +95,7 @@ public class HttpConnection extends AbstractConnection implements Dumpable
public boolean send(HttpExchange ex) throws IOException
{
LOG.debug("Send {} on {}",ex,this);
synchronized (this)
{
if (_exchange != null)
@ -124,16 +119,6 @@ public class HttpConnection extends AbstractConnection implements Dumpable
_exchange.setStatus(HttpExchange.STATUS_WAITING_FOR_COMMIT);
if (_endp.isBlocking())
{
this.notify();
}
else
{
AsyncEndPoint scep = (AsyncEndPoint)_endp;
scep.scheduleWrite();
}
adjustIdleTimeout();
return true;
@ -162,308 +147,8 @@ public class HttpConnection extends AbstractConnection implements Dumpable
}
}
public Connection handle() throws IOException
{
try
{
int no_progress = 0;
public abstract Connection handle() throws IOException;
boolean failed = false;
while (_endp.isBufferingInput() || _endp.isOpen())
{
synchronized (this)
{
while (_exchange == null)
{
if (_endp.isBlocking())
{
try
{
this.wait();
}
catch (InterruptedException e)
{
throw new InterruptedIOException();
}
}
else
{
long filled = _parser.fill();
if (filled < 0)
{
close();
}
else
{
// Hopefully just space?
_parser.skipCRLF();
if (_parser.isMoreInBuffer())
{
LOG.warn("Unexpected data received but no request sent");
close();
}
}
return this;
}
}
}
try
{
if (_exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT)
{
no_progress = 0;
commitRequest();
}
long io = 0;
_endp.flush();
if (_generator.isComplete())
{
if (!_requestComplete)
{
_requestComplete = true;
_exchange.getEventListener().onRequestComplete();
}
}
else
{
// Write as much of the request as possible
synchronized (this)
{
if (_exchange == null)
continue;
}
long flushed = _generator.flushBuffer();
io += flushed;
if (!_generator.isComplete())
{
if (_exchange!=null)
{
InputStream in = _exchange.getRequestContentSource();
if (in != null)
{
if (_requestContentChunk == null || _requestContentChunk.length() == 0)
{
_requestContentChunk = _exchange.getRequestContentChunk();
if (_requestContentChunk != null)
_generator.addContent(_requestContentChunk,false);
else
_generator.complete();
flushed = _generator.flushBuffer();
io += flushed;
}
}
else
_generator.complete();
}
else
_generator.complete();
}
}
if (_generator.isComplete() && !_requestComplete)
{
_requestComplete = true;
_exchange.getEventListener().onRequestComplete();
}
// If we are not ended then parse available
if (!_parser.isComplete() && (_generator.isComplete() || _generator.isCommitted() && !_endp.isBlocking()))
{
long filled = _parser.parseAvailable();
io += filled;
if (_parser.isIdle() && (_endp.isInputShutdown() || !_endp.isOpen()))
throw new EofException();
}
if (io > 0)
no_progress = 0;
else if (no_progress++ >= 1 && !_endp.isBlocking())
{
// SSL may need an extra flush as it may have made "no progress" while actually doing a handshake.
if (_endp instanceof SslSelectChannelEndPoint && !_generator.isComplete() && !_generator.isEmpty())
{
long flushed = _generator.flushBuffer();
if (flushed>0)
continue;
}
return this;
}
}
catch (Throwable e)
{
LOG.debug("Failure on " + _exchange, e);
if (e instanceof ThreadDeath)
throw (ThreadDeath)e;
failed = true;
synchronized (this)
{
if (_exchange != null)
{
// Cancelling the exchange causes an exception as we close the connection,
// but we don't report it as it is normal cancelling operation
if (_exchange.getStatus() != HttpExchange.STATUS_CANCELLING &&
_exchange.getStatus() != HttpExchange.STATUS_CANCELLED)
{
_exchange.setStatus(HttpExchange.STATUS_EXCEPTED);
_exchange.getEventListener().onException(e);
}
}
else
{
if (e instanceof IOException)
throw (IOException)e;
if (e instanceof Error)
throw (Error)e;
if (e instanceof RuntimeException)
throw (RuntimeException)e;
throw new RuntimeException(e);
}
}
}
finally
{
boolean complete = false;
boolean close = failed; // always close the connection on error
if (!failed)
{
// are we complete?
if (_generator.isComplete())
{
if (!_requestComplete)
{
_requestComplete = true;
_exchange.getEventListener().onRequestComplete();
}
// we need to return the HttpConnection to a state that
// it can be reused or closed out
if (_parser.isComplete())
{
_exchange.cancelTimeout(_destination.getHttpClient());
complete = true;
}
}
// if the endpoint is closed, but the parser incomplete
if (!_endp.isOpen() && !(_parser.isComplete()||_parser.isIdle()))
{
// we wont be called again so let the parser see the close
complete=true;
_parser.parseAvailable();
// TODO should not need this
if (!(_parser.isComplete()||_parser.isIdle()))
{
LOG.warn("Incomplete {} {}",_parser,_endp);
if (_exchange!=null && !_exchange.isDone())
{
_exchange.setStatus(HttpExchange.STATUS_EXCEPTED);
_exchange.getEventListener().onException(new EOFException("Incomplete"));
}
}
}
}
if (_endp.isInputShutdown() && !_parser.isComplete() && !_parser.isIdle())
{
if (_exchange!=null && !_exchange.isDone())
{
_exchange.setStatus(HttpExchange.STATUS_EXCEPTED);
_exchange.getEventListener().onException(new EOFException("Incomplete"));
}
_endp.close();
}
if (complete || failed)
{
synchronized (this)
{
if (!close)
close = shouldClose();
reset(true);
no_progress = 0;
if (_exchange != null)
{
HttpExchange exchange=_exchange;
_exchange = null;
// Reset the maxIdleTime because it may have been changed
if (!close)
_endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout());
if (_status==HttpStatus.SWITCHING_PROTOCOLS_101)
{
Connection switched=exchange.onSwitchProtocol(_endp);
if (switched!=null)
{
// switched protocol!
exchange = _pipeline;
_pipeline = null;
if (exchange!=null)
_destination.send(exchange);
return switched;
}
}
if (_pipeline == null)
{
if (!isReserved())
_destination.returnConnection(this, close);
}
else
{
if (close)
{
if (!isReserved())
_destination.returnConnection(this,close);
exchange = _pipeline;
_pipeline = null;
_destination.send(exchange);
}
else
{
exchange = _pipeline;
_pipeline = null;
send(exchange);
}
}
}
}
}
}
}
}
finally
{
_parser.returnBuffers();
// Do we have more stuff to write?
if (!_generator.isComplete() && _generator.getBytesBuffered()>0 && _endp.isOpen() && _endp instanceof AsyncEndPoint)
{
// Assume we are write blocked!
((AsyncEndPoint)_endp).scheduleWrite();
}
}
return this;
}
public boolean isIdle()
{
@ -478,11 +163,11 @@ public class HttpConnection extends AbstractConnection implements Dumpable
return false;
}
public void closed()
public void onClose()
{
}
private void commitRequest() throws IOException
protected void commitRequest() throws IOException
{
synchronized (this)
{
@ -558,30 +243,14 @@ public class HttpConnection extends AbstractConnection implements Dumpable
}
}
protected void reset(boolean returnBuffers) throws IOException
protected void reset() throws IOException
{
_requestComplete = false;
_connectionHeader = null;
_parser.reset();
if (returnBuffers)
_parser.returnBuffers();
_generator.reset(returnBuffers);
_generator.reset();
_http11 = true;
}
private boolean shouldClose()
{
if (_endp.isInputShutdown())
return true;
if (_connectionHeader!=null)
{
if (HttpHeaderValues.CLOSE_BUFFER.equals(_connectionHeader))
return true;
if (HttpHeaderValues.KEEP_ALIVE_BUFFER.equals(_connectionHeader))
return false;
}
return !_http11;
}
private class Handler extends HttpParser.EventHandler
{
@ -599,8 +268,13 @@ public class HttpConnection extends AbstractConnection implements Dumpable
public void startResponse(Buffer version, int status, Buffer reason) throws IOException
{
HttpExchange exchange = _exchange;
if (exchange!=null)
if (exchange==null)
{
LOG.warn("No exchange for response");
_endp.close();
return;
}
switch(status)
{
case HttpStatus.CONTINUE_100:
@ -620,7 +294,7 @@ public class HttpConnection extends AbstractConnection implements Dumpable
_status=status;
exchange.getEventListener().onResponseStatus(version,status,reason);
exchange.setStatus(HttpExchange.STATUS_PARSING_HEADERS);
}
}
@Override
@ -640,8 +314,6 @@ public class HttpConnection extends AbstractConnection implements Dumpable
@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);
@ -650,8 +322,6 @@ public class HttpConnection extends AbstractConnection implements Dumpable
@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);
@ -664,12 +334,33 @@ public class HttpConnection extends AbstractConnection implements Dumpable
if (exchange!=null)
exchange.setStatus(HttpExchange.STATUS_COMPLETED);
}
@Override
public void earlyEOF()
{
HttpExchange exchange = _exchange;
if (exchange!=null)
{
if (!exchange.isDone())
{
if (exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(new EofException("early EOF"));
}
}
}
}
@Override
public String toString()
{
return "HttpConnection@" + hashCode() + "//" + _destination.getAddress().getHost() + ":" + _destination.getAddress().getPort();
return String.format("%s@%x//%s,g=%s,p=%s",
getClass().getSimpleName(),
hashCode(),
_destination == null ? "?.?.?.?:??" : _destination.getAddress(),
_generator,
_parser);
}
public String toDetailString()
@ -699,8 +390,8 @@ public class HttpConnection extends AbstractConnection implements Dumpable
default:
String exch= exchange.toString();
String reason = _endp.isOpen()?(_endp.isInputShutdown()?"half closed: ":"local close: "):"closed: ";
exchange.setStatus(HttpExchange.STATUS_EXCEPTED);
exchange.getEventListener().onException(new EOFException(reason+exch));
if (exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(new EofException(reason+exch));
}
}
@ -784,7 +475,7 @@ public class HttpConnection extends AbstractConnection implements Dumpable
// Connection idle, close it
if (_idle.compareAndSet(true, false))
{
_destination.returnIdleConnection(HttpConnection.this);
_destination.returnIdleConnection(AbstractHttpConnection.this);
}
}
}

View File

@ -0,0 +1,260 @@
// ========================================================================
// Copyright (c) 2006-2011 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;
import java.io.IOException;
import org.eclipse.jetty.http.AbstractGenerator;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** Asynchronous Client HTTP Connection
*/
public class AsyncHttpConnection extends AbstractHttpConnection implements AsyncConnection
{
private static final Logger LOG = Log.getLogger(AsyncHttpConnection.class);
private boolean _requestComplete;
private Buffer _requestContentChunk;
private final AsyncEndPoint _asyncEndp;
AsyncHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endp)
{
super(requestBuffers,responseBuffers,endp);
_asyncEndp=(AsyncEndPoint)endp;
}
protected void reset() throws IOException
{
_requestComplete = false;
super.reset();
}
public Connection handle() throws IOException
{
Connection connection = this;
boolean progress=true;
try
{
boolean failed = false;
// While we are making progress and have not changed connection
while (progress && connection==this)
{
LOG.debug("while open={} more={} progress={}",_endp.isOpen(),_parser.isMoreInBuffer(),progress);
progress=false;
HttpExchange exchange=_exchange;
LOG.debug("exchange {} on {}",exchange,this);
try
{
// Should we commit the request?
if (!_generator.isCommitted() && exchange!=null && exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT)
{
LOG.debug("commit {}",exchange);
progress=true;
commitRequest();
}
// Generate output
if (_generator.isCommitted() && !_generator.isComplete())
{
if (_generator.flushBuffer()>0)
{
LOG.debug("flushed");
progress=true;
}
// Is there more content to send or should we complete the generator
if (_generator.isState(AbstractGenerator.STATE_CONTENT))
{
// Look for more content to send.
if (_requestContentChunk==null)
_requestContentChunk = exchange.getRequestContentChunk(null);
if (_requestContentChunk==null)
{
LOG.debug("complete {}",exchange);
progress=true;
_generator.complete();
}
else if (_generator.isEmpty())
{
LOG.debug("addChunk");
progress=true;
Buffer chunk=_requestContentChunk;
_requestContentChunk=exchange.getRequestContentChunk(null);
_generator.addContent(chunk,_requestContentChunk==null);
}
}
}
// Signal request completion
if (_generator.isComplete() && !_requestComplete)
{
LOG.debug("requestComplete {}",exchange);
progress=true;
_requestComplete = true;
exchange.getEventListener().onRequestComplete();
}
// Read any input that is available
if (!_parser.isComplete() && _parser.parseAvailable())
{
LOG.debug("parsed {}",exchange);
progress=true;
}
// Flush output
_endp.flush();
// Has any IO been done by the endpoint itself since last loop
if (_asyncEndp.hasProgressed())
{
LOG.debug("hasProgressed {}",exchange);
progress=true;
}
}
catch (Throwable e)
{
LOG.debug("Failure on " + _exchange, e);
failed = true;
synchronized (this)
{
if (exchange != null)
{
// Cancelling the exchange causes an exception as we close the connection,
// but we don't report it as it is normal cancelling operation
if (exchange.getStatus() != HttpExchange.STATUS_CANCELLING &&
exchange.getStatus() != HttpExchange.STATUS_CANCELLED &&
!exchange.isDone())
{
if (exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(e);
}
}
else
{
if (e instanceof IOException)
throw (IOException)e;
if (e instanceof Error)
throw (Error)e;
if (e instanceof RuntimeException)
throw (RuntimeException)e;
throw new RuntimeException(e);
}
}
}
finally
{
LOG.debug("finally {} on {} progress={} {}",exchange,this,progress,_endp);
boolean complete = failed || _generator.isComplete() && _parser.isComplete();
if (complete)
{
boolean persistent = !failed && _parser.isPersistent() && _generator.isPersistent();
_generator.setPersistent(persistent);
reset();
if (persistent)
_endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout());
synchronized (this)
{
exchange=_exchange;
_exchange = null;
// Cancel the exchange
if (exchange!=null)
{
exchange.cancelTimeout(_destination.getHttpClient());
// TODO should we check the exchange is done?
}
// handle switched protocols
if (_status==HttpStatus.SWITCHING_PROTOCOLS_101)
{
Connection switched=exchange.onSwitchProtocol(_endp);
if (switched!=null)
connection=switched;
{
// switched protocol!
_pipeline = null;
if (_pipeline!=null)
_destination.send(_pipeline);
_pipeline = null;
connection=switched;
}
}
// handle pipelined requests
if (_pipeline!=null)
{
if (!persistent || connection!=this)
_destination.send(_pipeline);
else
_exchange=_pipeline;
_pipeline=null;
}
if (_exchange==null && !isReserved()) // TODO how do we return switched connections?
_destination.returnConnection(this, !persistent);
}
}
}
}
}
finally
{
_parser.returnBuffers();
_generator.returnBuffers();
LOG.debug("unhandle {} on {}",_exchange,_endp);
}
return connection;
}
public void onInputShutdown() throws IOException
{
if (_generator.isIdle())
_endp.shutdownOutput();
}
@Override
public boolean send(HttpExchange ex) throws IOException
{
boolean sent=super.send(ex);
if (sent)
_asyncEndp.asyncDispatch();
return sent;
}
}

View File

@ -0,0 +1,257 @@
// ========================================================================
// Copyright (c) 2006-2011 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;
import java.io.IOException;
import java.io.InterruptedIOException;
import org.eclipse.jetty.http.AbstractGenerator;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** Blocking HTTP Connection
*/
public class BlockingHttpConnection extends AbstractHttpConnection
{
private static final Logger LOG = Log.getLogger(BlockingHttpConnection.class);
private boolean _requestComplete;
private Buffer _requestContentChunk;
BlockingHttpConnection(Buffers requestBuffers, Buffers responseBuffers, EndPoint endPoint)
{
super(requestBuffers, responseBuffers, endPoint);
}
protected void reset() throws IOException
{
_requestComplete = false;
super.reset();
}
@Override
public Connection handle() throws IOException
{
Connection connection = this;
try
{
boolean failed = false;
// While we are making progress and have not changed connection
while (_endp.isOpen() && connection==this)
{
LOG.debug("open={} more={}",_endp.isOpen(),_parser.isMoreInBuffer());
HttpExchange exchange;
synchronized (this)
{
exchange=_exchange;
while (exchange == null)
{
try
{
this.wait();
exchange=_exchange;
}
catch (InterruptedException e)
{
throw new InterruptedIOException();
}
}
}
LOG.debug("exchange {}",exchange);
try
{
// Should we commit the request?
if (!_generator.isCommitted() && exchange!=null && exchange.getStatus() == HttpExchange.STATUS_WAITING_FOR_COMMIT)
{
LOG.debug("commit");
commitRequest();
}
// Generate output
while (_generator.isCommitted() && !_generator.isComplete())
{
if (_generator.flushBuffer()>0)
{
LOG.debug("flushed");
}
// Is there more content to send or should we complete the generator
if (_generator.isState(AbstractGenerator.STATE_CONTENT))
{
// Look for more content to send.
if (_requestContentChunk==null)
_requestContentChunk = exchange.getRequestContentChunk(null);
if (_requestContentChunk==null)
{
LOG.debug("complete");
_generator.complete();
}
else if (_generator.isEmpty())
{
LOG.debug("addChunk");
Buffer chunk=_requestContentChunk;
_requestContentChunk=exchange.getRequestContentChunk(null);
_generator.addContent(chunk,_requestContentChunk==null);
}
}
}
// Signal request completion
if (_generator.isComplete() && !_requestComplete)
{
LOG.debug("requestComplete");
_requestComplete = true;
exchange.getEventListener().onRequestComplete();
}
// Read any input that is available
if (!_parser.isComplete() && _parser.parseAvailable())
{
LOG.debug("parsed");
}
// Flush output
_endp.flush();
}
catch (Throwable e)
{
LOG.debug("Failure on " + _exchange, e);
failed = true;
synchronized (this)
{
if (exchange != null)
{
// Cancelling the exchange causes an exception as we close the connection,
// but we don't report it as it is normal cancelling operation
if (exchange.getStatus() != HttpExchange.STATUS_CANCELLING &&
exchange.getStatus() != HttpExchange.STATUS_CANCELLED &&
!exchange.isDone())
{
if(exchange.setStatus(HttpExchange.STATUS_EXCEPTED))
exchange.getEventListener().onException(e);
}
}
else
{
if (e instanceof IOException)
throw (IOException)e;
if (e instanceof Error)
throw (Error)e;
if (e instanceof RuntimeException)
throw (RuntimeException)e;
throw new RuntimeException(e);
}
}
}
finally
{
LOG.debug("{} {}",_generator, _parser);
LOG.debug("{}",_endp);
boolean complete = failed || _generator.isComplete() && _parser.isComplete();
if (complete)
{
boolean persistent = !failed && _parser.isPersistent() && _generator.isPersistent();
_generator.setPersistent(persistent);
reset();
if (persistent)
_endp.setMaxIdleTime((int)_destination.getHttpClient().getIdleTimeout());
synchronized (this)
{
exchange=_exchange;
_exchange = null;
// Cancel the exchange
if (exchange!=null)
{
exchange.cancelTimeout(_destination.getHttpClient());
// TODO should we check the exchange is done?
}
// handle switched protocols
if (_status==HttpStatus.SWITCHING_PROTOCOLS_101)
{
Connection switched=exchange.onSwitchProtocol(_endp);
if (switched!=null)
connection=switched;
{
// switched protocol!
_pipeline = null;
if (_pipeline!=null)
_destination.send(_pipeline);
_pipeline = null;
connection=switched;
}
}
// handle pipelined requests
if (_pipeline!=null)
{
if (!persistent || connection!=this)
_destination.send(_pipeline);
else
_exchange=_pipeline;
_pipeline=null;
}
if (_exchange==null && !isReserved()) // TODO how do we return switched connections?
_destination.returnConnection(this, !persistent);
}
}
}
}
}
finally
{
_parser.returnBuffers();
_generator.returnBuffers();
}
return connection;
}
@Override
public boolean send(HttpExchange ex) throws IOException
{
boolean sent=super.send(ex);
if (sent)
{
synchronized (this)
{
notifyAll();
}
}
return sent;
}
}

View File

@ -16,6 +16,7 @@ package org.eclipse.jetty.client;
import java.io.IOException;
import java.io.InputStream;
import java.net.UnknownHostException;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.LinkedList;
import java.util.Set;
@ -29,13 +30,13 @@ import org.eclipse.jetty.client.security.RealmResolver;
import org.eclipse.jetty.client.security.SecurityListener;
import org.eclipse.jetty.http.HttpBuffers;
import org.eclipse.jetty.http.HttpSchemes;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.io.Buffers.Type;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.eclipse.jetty.util.thread.Timeout;
@ -52,11 +53,11 @@ import org.eclipse.jetty.util.thread.Timeout;
* The an instance of {@link HttpExchange} is passed to the {@link #send(HttpExchange)} method
* to send a request. The exchange contains both the headers and content (source) of the request
* plus the callbacks to handle responses. A HttpClient can have many exchanges outstanding
* and they may be queued on the {@link HttpDestination} waiting for a {@link HttpConnection},
* queued in the {@link HttpConnection} waiting to be transmitted or pipelined on the actual
* and they may be queued on the {@link HttpDestination} waiting for a {@link AbstractHttpConnection},
* queued in the {@link AbstractHttpConnection} waiting to be transmitted or pipelined on the actual
* TCP/IP connection waiting for a response.
* <p/>
* The {@link HttpDestination} class is an aggregation of {@link HttpConnection}s for the
* The {@link HttpDestination} class is an aggregation of {@link AbstractHttpConnection}s for the
* same host, port and protocol. A destination may limit the number of connections
* open and they provide a pool of open connections that may be reused. Connections may also
* be allocated from a destination, so that multiple request sources are not multiplexed
@ -164,7 +165,7 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
public void dump(Appendable out, String indent) throws IOException
{
out.append(String.valueOf(this)).append("\n");
AggregateLifeCycle.dump(out,indent,_destinations.values());
AggregateLifeCycle.dump(out,indent,Arrays.asList(_threadPool,_connector),_destinations.values());
}
/* ------------------------------------------------------------------------------- */
@ -526,7 +527,7 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
/* ------------------------------------------------------------ */
/**
* @return the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
* @return the period in milliseconds a {@link AbstractHttpConnection} can be idle for before it is closed.
*/
public long getIdleTimeout()
{
@ -535,7 +536,7 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
/* ------------------------------------------------------------ */
/**
* @param ms the period in milliseconds a {@link HttpConnection} can be idle for before it is closed.
* @param ms the period in milliseconds a {@link AbstractHttpConnection} can be idle for before it is closed.
*/
public void setIdleTimeout(long ms)
{

View File

@ -15,7 +15,7 @@ package org.eclipse.jetty.client;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.net.ConnectException;
import java.net.ProtocolException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
@ -48,9 +48,9 @@ public class HttpDestination implements Dumpable
private static final Logger LOG = Log.getLogger(HttpDestination.class);
private final List<HttpExchange> _queue = new LinkedList<HttpExchange>();
private final List<HttpConnection> _connections = new LinkedList<HttpConnection>();
private final List<AbstractHttpConnection> _connections = new LinkedList<AbstractHttpConnection>();
private final BlockingQueue<Object> _newQueue = new ArrayBlockingQueue<Object>(10, true);
private final List<HttpConnection> _idle = new ArrayList<HttpConnection>();
private final List<AbstractHttpConnection> _idle = new ArrayList<AbstractHttpConnection>();
private final HttpClient _client;
private final Address _address;
private final boolean _ssl;
@ -168,9 +168,9 @@ public class HttpDestination implements Dumpable
* @return a HttpConnection for this destination
* @throws IOException if an I/O error occurs
*/
private HttpConnection getConnection(long timeout) throws IOException
private AbstractHttpConnection getConnection(long timeout) throws IOException
{
HttpConnection connection = null;
AbstractHttpConnection connection = null;
while ((connection == null) && (connection = getIdleConnection()) == null && timeout > 0)
{
@ -191,9 +191,9 @@ public class HttpDestination implements Dumpable
try
{
Object o = _newQueue.take();
if (o instanceof HttpConnection)
if (o instanceof AbstractHttpConnection)
{
connection = (HttpConnection)o;
connection = (AbstractHttpConnection)o;
}
else
throw (IOException)o;
@ -220,17 +220,17 @@ public class HttpDestination implements Dumpable
return connection;
}
public HttpConnection reserveConnection(long timeout) throws IOException
public AbstractHttpConnection reserveConnection(long timeout) throws IOException
{
HttpConnection connection = getConnection(timeout);
AbstractHttpConnection connection = getConnection(timeout);
if (connection != null)
connection.setReserved(true);
return connection;
}
public HttpConnection getIdleConnection() throws IOException
public AbstractHttpConnection getIdleConnection() throws IOException
{
HttpConnection connection = null;
AbstractHttpConnection connection = null;
while (true)
{
synchronized (this)
@ -246,14 +246,18 @@ public class HttpDestination implements Dumpable
}
if (connection == null)
{
return null;
}
// Check if the connection was idle,
// but it expired just a moment ago
if (connection.cancelIdleTimeout())
{
return connection;
}
}
}
protected void startNewConnection()
{
@ -290,7 +294,7 @@ public class HttpDestination implements Dumpable
else if (_queue.size() > 0)
{
HttpExchange ex = _queue.remove(0);
ex.setStatus(HttpExchange.STATUS_EXCEPTED);
if (ex.setStatus(HttpExchange.STATUS_EXCEPTED))
ex.getEventListener().onConnectionFailed(throwable);
// Since an existing connection had failed, we need to create a
@ -324,13 +328,13 @@ public class HttpDestination implements Dumpable
if (_queue.size() > 0)
{
HttpExchange ex = _queue.remove(0);
ex.setStatus(HttpExchange.STATUS_EXCEPTED);
if(ex.setStatus(HttpExchange.STATUS_EXCEPTED))
ex.getEventListener().onException(throwable);
}
}
}
public void onNewConnection(final HttpConnection connection) throws IOException
public void onNewConnection(final AbstractHttpConnection connection) throws IOException
{
Connection q_connection = null;
@ -352,9 +356,9 @@ public class HttpDestination implements Dumpable
else
{
EndPoint endPoint = connection.getEndPoint();
if (isProxied() && endPoint instanceof SelectConnector.ProxySelectChannelEndPoint)
if (isProxied() && endPoint instanceof SelectConnector.UpgradableEndPoint)
{
SelectConnector.ProxySelectChannelEndPoint proxyEndPoint = (SelectConnector.ProxySelectChannelEndPoint)endPoint;
SelectConnector.UpgradableEndPoint proxyEndPoint = (SelectConnector.UpgradableEndPoint)endPoint;
HttpExchange exchange = _queue.get(0);
ConnectExchange connect = new ConnectExchange(getAddress(), proxyEndPoint, exchange);
connect.setAddress(getProxy());
@ -381,7 +385,7 @@ public class HttpDestination implements Dumpable
}
}
public void returnConnection(HttpConnection connection, boolean close) throws IOException
public void returnConnection(AbstractHttpConnection connection, boolean close) throws IOException
{
if (connection.isReserved())
connection.setReserved(false);
@ -433,16 +437,9 @@ public class HttpDestination implements Dumpable
}
}
public void returnIdleConnection(HttpConnection connection)
public void returnIdleConnection(AbstractHttpConnection connection)
{
try
{
connection.close();
}
catch (IOException e)
{
LOG.ignore(e);
}
connection.onIdleExpired();
boolean startConnection = false;
synchronized (this)
@ -524,7 +521,7 @@ public class HttpDestination implements Dumpable
// Add any known authorizations
if (_authorizations != null)
{
Authentication auth = (Authentication)_authorizations.match(ex.getURI());
Authentication auth = (Authentication)_authorizations.match(ex.getRequestURI());
if (auth != null)
(auth).setCredentials(ex);
}
@ -533,7 +530,7 @@ public class HttpDestination implements Dumpable
// so that we count also the queue time in the timeout
ex.scheduleTimeout(this);
HttpConnection connection = getIdleConnection();
AbstractHttpConnection connection = getIdleConnection();
if (connection != null)
{
send(connection, ex);
@ -566,7 +563,7 @@ public class HttpDestination implements Dumpable
}
}
protected void send(HttpConnection connection, HttpExchange exchange) throws IOException
protected void send(AbstractHttpConnection connection, HttpExchange exchange) throws IOException
{
synchronized (this)
{
@ -594,7 +591,7 @@ public class HttpDestination implements Dumpable
b.append('\n');
synchronized (this)
{
for (HttpConnection connection : _connections)
for (AbstractHttpConnection connection : _connections)
{
b.append(connection.toDetailString());
if (_idle.contains(connection))
@ -637,7 +634,7 @@ public class HttpDestination implements Dumpable
{
synchronized (this)
{
for (HttpConnection connection : _connections)
for (AbstractHttpConnection connection : _connections)
{
connection.close();
}
@ -668,10 +665,10 @@ public class HttpDestination implements Dumpable
private class ConnectExchange extends ContentExchange
{
private final SelectConnector.ProxySelectChannelEndPoint proxyEndPoint;
private final SelectConnector.UpgradableEndPoint proxyEndPoint;
private final HttpExchange exchange;
public ConnectExchange(Address serverAddress, SelectConnector.ProxySelectChannelEndPoint proxyEndPoint, HttpExchange exchange)
public ConnectExchange(Address serverAddress, SelectConnector.UpgradableEndPoint proxyEndPoint, HttpExchange exchange)
{
this.proxyEndPoint = proxyEndPoint;
this.exchange = exchange;
@ -687,13 +684,18 @@ public class HttpDestination implements Dumpable
@Override
protected void onResponseComplete() throws IOException
{
if (getResponseStatus() == HttpStatus.OK_200)
int responseStatus = getResponseStatus();
if (responseStatus == HttpStatus.OK_200)
{
proxyEndPoint.upgrade();
}
else if(responseStatus == HttpStatus.GATEWAY_TIMEOUT_504)
{
onExpire();
}
else
{
onConnectionFailed(new ConnectException(exchange.getAddress().toString()));
onException(new ProtocolException("Proxy: " + proxyEndPoint.getRemoteAddr() +":" + proxyEndPoint.getRemotePort() + " didn't return http return code 200, but " + responseStatus + " while trying to request: " + exchange.getAddress().toString()));
}
}
@ -702,5 +704,22 @@ public class HttpDestination implements Dumpable
{
HttpDestination.this.onConnectionFailed(x);
}
@Override
protected void onException(Throwable x)
{
_queue.remove(exchange);
if (exchange.setStatus(STATUS_EXCEPTED))
exchange.getEventListener().onException(x);
}
@Override
protected void onExpire()
{
_queue.remove(exchange);
if (exchange.setStatus(STATUS_EXPIRED))
exchange.getEventListener().onExpire();
}
}
}

View File

@ -59,7 +59,7 @@ import org.eclipse.jetty.util.thread.Timeout;
*
* <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)}. A
* {@link HttpDestination#send(HttpExchange)}, which then creates or selects a {@link AbstractHttpConnection} and calls its {@link AbstractHttpConnection#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>
@ -72,7 +72,7 @@ import org.eclipse.jetty.util.thread.Timeout;
*/
public class HttpExchange
{
private static final Logger LOG = Log.getLogger(HttpExchange.class);
static final Logger LOG = Log.getLogger(HttpExchange.class);
public static final int STATUS_START = 0;
public static final int STATUS_WAITING_FOR_CONNECTION = 1;
@ -98,12 +98,11 @@ public class HttpExchange
private InputStream _requestContentSource;
private AtomicInteger _status = new AtomicInteger(STATUS_START);
private Buffer _requestContentChunk;
private boolean _retryStatus = false;
// controls if the exchange will have listeners autoconfigured by the destination
private boolean _configureListeners = true;
private HttpEventListener _listener = new Listener();
private volatile HttpConnection _connection;
private volatile AbstractHttpConnection _connection;
private Address _localAddress = null;
@ -123,9 +122,8 @@ public class HttpExchange
{
if (getStatus() < HttpExchange.STATUS_COMPLETED)
setStatus(HttpExchange.STATUS_EXPIRED);
destination.exchangeExpired(this);
HttpConnection connection = _connection;
AbstractHttpConnection connection = _connection;
if (connection != null)
connection.exchangeExpired(this);
}
@ -183,12 +181,18 @@ public class HttpExchange
}
}
void setStatus(int newStatus)
/* ------------------------------------------------------------ */
/**
* @param newStatus
* @return True if the status was actually set.
*/
boolean setStatus(int newStatus)
{
boolean set = false;
try
{
int oldStatus = _status.get();
boolean set = false;
boolean ignored = false;
if (oldStatus != newStatus)
{
long now = System.currentTimeMillis();
@ -315,7 +319,7 @@ public class HttpExchange
case STATUS_CANCELLING:
case STATUS_EXPIRED:
// Don't change the status, it's too late
set = true;
ignored = true;
break;
}
break;
@ -329,7 +333,7 @@ public class HttpExchange
break;
default:
// Ignore other statuses, we're cancelling
set = true;
ignored = true;
break;
}
break;
@ -341,8 +345,14 @@ public class HttpExchange
case STATUS_START:
set = _status.compareAndSet(oldStatus,newStatus);
break;
case STATUS_COMPLETED:
ignored = true;
done();
break;
default:
set = true;
ignored = true;
break;
}
break;
@ -351,13 +361,15 @@ public class HttpExchange
throw new AssertionError(oldStatus + " => " + newStatus);
}
if (!set)
if (!set && !ignored)
throw new IllegalStateException(toState(oldStatus) + " => " + toState(newStatus));
LOG.debug("setStatus {} {}",newStatus,this);
}
catch (IOException x)
{
LOG.warn(x);
}
return set;
}
private boolean setStatusExpired(int newStatus, int oldStatus)
@ -706,25 +718,22 @@ public class HttpExchange
return _requestContentSource;
}
public Buffer getRequestContentChunk() throws IOException
public Buffer getRequestContentChunk(Buffer buffer) throws IOException
{
synchronized (this)
{
if (_requestContentChunk == null)
_requestContentChunk = new ByteArrayBuffer(4096); // TODO configure
else
if (_requestContentSource!=null)
{
if (_requestContentChunk.hasContent())
throw new IllegalStateException();
_requestContentChunk.clear();
}
if (buffer == null)
buffer = new ByteArrayBuffer(8192); // TODO configure
int read = _requestContentChunk.capacity();
int length = _requestContentSource.read(_requestContentChunk.array(),0,read);
int space = buffer.space();
int length = _requestContentSource.read(buffer.array(),buffer.putIndex(),space);
if (length >= 0)
{
_requestContentChunk.setPutIndex(length);
return _requestContentChunk;
buffer.setPutIndex(buffer.putIndex()+length);
return buffer;
}
}
return null;
}
@ -779,7 +788,7 @@ public class HttpExchange
private void abort()
{
HttpConnection httpConnection = _connection;
AbstractHttpConnection httpConnection = _connection;
if (httpConnection != null)
{
try
@ -799,7 +808,7 @@ public class HttpExchange
}
}
void associate(HttpConnection connection)
void associate(AbstractHttpConnection connection)
{
if (connection.getEndPoint().getLocalHost() != null)
_localAddress = new Address(connection.getEndPoint().getLocalHost(),connection.getEndPoint().getLocalPort());
@ -814,9 +823,9 @@ public class HttpExchange
return this._connection != null;
}
HttpConnection disassociate()
AbstractHttpConnection disassociate()
{
HttpConnection result = _connection;
AbstractHttpConnection result = _connection;
this._connection = null;
if (getStatus() == STATUS_CANCELLING)
setStatus(STATUS_CANCELLED);

View File

@ -15,43 +15,39 @@ 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.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.Buffers;
import org.eclipse.jetty.io.Buffers.Type;
import org.eclipse.jetty.io.BuffersFactory;
import org.eclipse.jetty.io.ConnectedEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.nio.AsyncConnection;
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.io.nio.SslConnection;
import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.component.Dumpable;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.Timeout;
import org.eclipse.jetty.util.thread.Timeout.Task;
class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector, Dumpable
{
private static final Logger LOG = Log.getLogger(SelectConnector.class);
private final HttpClient _httpClient;
private final Manager _selectorManager=new Manager();
private final Map<SocketChannel, Timeout.Task> _connectingChannels = new ConcurrentHashMap<SocketChannel, Timeout.Task>();
private Buffers _sslBuffers;
/**
* @param httpClient the HttpClient this connector is associated to
@ -67,16 +63,6 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
{
super.doStart();
final boolean direct=_httpClient.getUseDirectBuffers();
SSLEngine sslEngine=_selectorManager.newSslEngine(null);
final SSLSession ssl_session=sslEngine.getSession();
_sslBuffers = BuffersFactory.newBuffers(
direct?Type.DIRECT:Type.INDIRECT,ssl_session.getApplicationBufferSize(),
direct?Type.DIRECT:Type.INDIRECT,ssl_session.getApplicationBufferSize(),
direct?Type.DIRECT:Type.INDIRECT,1024);
_selectorManager.start();
}
@ -87,6 +73,17 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
_selectorManager.stop();
}
public String dump()
{
return AggregateLifeCycle.dump(this);
}
public void dump(Appendable out, String indent) throws IOException
{
out.append(String.valueOf(this)).append("\n");
AggregateLifeCycle.dump(out, indent, Arrays.asList(_selectorManager));
}
/* ------------------------------------------------------------ */
public void startConnection( HttpDestination destination )
throws IOException
@ -131,6 +128,8 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
/* ------------------------------------------------------------ */
class Manager extends SelectorManager
{
Logger LOG = SelectConnector.LOG;
@Override
public boolean dispatch(Runnable task)
{
@ -153,12 +152,9 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
}
@Override
protected Connection newConnection(SocketChannel channel, SelectChannelEndPoint endpoint)
public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment)
{
if (endpoint instanceof SslSelectChannelEndPoint)
return new HttpConnection(_sslBuffers,_sslBuffers,endpoint);
return new HttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint);
return new AsyncHttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint);
}
@Override
@ -174,32 +170,27 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
// key should have destination at this point (will be replaced by endpoint after this call)
HttpDestination dest=(HttpDestination)key.attachment();
SelectChannelEndPoint ep=null;
SelectChannelEndPoint scep = new SelectChannelEndPoint(channel, selectSet, key, (int)_httpClient.getIdleTimeout());
AsyncEndPoint ep = scep;
if (dest.isSecure())
{
if (dest.isProxied())
{
SSLEngine engine=newSslEngine(channel);
ep = new ProxySelectChannelEndPoint(channel, selectSet, key, _sslBuffers, engine, (int)_httpClient.getIdleTimeout());
}
else
{
SSLEngine engine=newSslEngine(channel);
SslSelectChannelEndPoint sslEp = new SslSelectChannelEndPoint(_sslBuffers, channel, selectSet, key, engine, (int)_httpClient.getIdleTimeout());
sslEp.setAllowRenegotiate(_httpClient.getSslContextFactory().isAllowRenegotiate());
ep = sslEp;
}
}
else
{
ep = new SelectChannelEndPoint(channel, selectSet, key, (int)_httpClient.getIdleTimeout());
LOG.debug("secure to {}, proxied={}",channel,dest.isProxied());
ep = new UpgradableEndPoint(ep,newSslEngine(channel));
}
HttpConnection connection=(HttpConnection)ep.getConnection();
connection.setDestination(dest);
dest.onNewConnection(connection);
return ep;
AsyncConnection connection = selectSet.getManager().newConnection(channel,ep, key.attachment());
ep.setConnection(connection);
AbstractHttpConnection httpConnection=(AbstractHttpConnection)connection;
httpConnection.setDestination(dest);
if (dest.isSecure() && !dest.isProxied())
((UpgradableEndPoint)ep).upgrade();
dest.onNewConnection(httpConnection);
return scep;
}
private synchronized SSLEngine newSslEngine(SocketChannel channel) throws IOException
@ -271,203 +262,200 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector
}
}
/**
* An endpoint that is able to "upgrade" from a normal endpoint to a SSL endpoint.
* Since {@link HttpParser} and {@link HttpGenerator} only depend on the {@link EndPoint}
* interface, this class overrides all methods of {@link EndPoint} to provide the right
* behavior depending on the fact that it has been upgraded or not.
*/
public static class ProxySelectChannelEndPoint extends SslSelectChannelEndPoint
public static class UpgradableEndPoint implements AsyncEndPoint
{
private final SelectChannelEndPoint plainEndPoint;
private volatile boolean upgraded = false;
AsyncEndPoint _endp;
SSLEngine _engine;
public ProxySelectChannelEndPoint(SocketChannel channel, SelectorManager.SelectSet selectSet, SelectionKey key, Buffers sslBuffers, SSLEngine engine, int maxIdleTimeout) throws IOException
public UpgradableEndPoint(AsyncEndPoint endp, SSLEngine engine) throws IOException
{
super(sslBuffers, channel, selectSet, key, engine, maxIdleTimeout);
this.plainEndPoint = new SelectChannelEndPoint(channel, selectSet, key, maxIdleTimeout);
_engine=engine;
_endp=endp;
}
public void upgrade()
{
upgraded = true;
AsyncHttpConnection connection = (AsyncHttpConnection)_endp.getConnection();
SslConnection sslConnection = new SslConnection(_engine,_endp);
_endp.setConnection(sslConnection);
_endp=sslConnection.getSslEndPoint();
sslConnection.getSslEndPoint().setConnection(connection);
LOG.debug("upgrade {} to {} for {}",this,sslConnection,connection);
}
public Connection getConnection()
{
return _endp.getConnection();
}
public void setConnection(Connection connection)
{
_endp.setConnection(connection);
}
public void shutdownOutput() throws IOException
{
if (upgraded)
super.shutdownOutput();
else
plainEndPoint.shutdownOutput();
_endp.shutdownOutput();
}
public void asyncDispatch()
{
_endp.asyncDispatch();
}
public boolean isOutputShutdown()
{
return _endp.isOutputShutdown();
}
public void shutdownInput() throws IOException
{
_endp.shutdownInput();
}
public void scheduleWrite()
{
_endp.scheduleWrite();
}
public boolean isInputShutdown()
{
return _endp.isInputShutdown();
}
public void close() throws IOException
{
if (upgraded)
super.close();
else
plainEndPoint.close();
_endp.close();
}
public int fill(Buffer buffer) throws IOException
{
if (upgraded)
return super.fill(buffer);
else
return plainEndPoint.fill(buffer);
return _endp.fill(buffer);
}
public boolean isWritable()
{
return _endp.isWritable();
}
public boolean hasProgressed()
{
return _endp.hasProgressed();
}
public int flush(Buffer buffer) throws IOException
{
if (upgraded)
return super.flush(buffer);
else
return plainEndPoint.flush(buffer);
return _endp.flush(buffer);
}
public void scheduleTimeout(Task task, long timeoutMs)
{
_endp.scheduleTimeout(task,timeoutMs);
}
public void cancelTimeout(Task task)
{
_endp.cancelTimeout(task);
}
public int flush(Buffer header, Buffer buffer, Buffer trailer) throws IOException
{
if (upgraded)
return super.flush(header, buffer, trailer);
else
return plainEndPoint.flush(header, buffer, trailer);
return _endp.flush(header,buffer,trailer);
}
public String getLocalAddr()
{
if (upgraded)
return super.getLocalAddr();
else
return plainEndPoint.getLocalAddr();
return _endp.getLocalAddr();
}
public String getLocalHost()
{
if (upgraded)
return super.getLocalHost();
else
return plainEndPoint.getLocalHost();
return _endp.getLocalHost();
}
public int getLocalPort()
{
if (upgraded)
return super.getLocalPort();
else
return plainEndPoint.getLocalPort();
return _endp.getLocalPort();
}
public String getRemoteAddr()
{
if (upgraded)
return super.getRemoteAddr();
else
return plainEndPoint.getRemoteAddr();
return _endp.getRemoteAddr();
}
public String getRemoteHost()
{
if (upgraded)
return super.getRemoteHost();
else
return plainEndPoint.getRemoteHost();
return _endp.getRemoteHost();
}
public int getRemotePort()
{
if (upgraded)
return super.getRemotePort();
else
return plainEndPoint.getRemotePort();
return _endp.getRemotePort();
}
public boolean isBlocking()
{
if (upgraded)
return super.isBlocking();
else
return plainEndPoint.isBlocking();
}
public boolean isBufferred()
{
if (upgraded)
return super.isBufferred();
else
return plainEndPoint.isBufferred();
return _endp.isBlocking();
}
public boolean blockReadable(long millisecs) throws IOException
{
if (upgraded)
return super.blockReadable(millisecs);
else
return plainEndPoint.blockReadable(millisecs);
return _endp.blockReadable(millisecs);
}
public boolean blockWritable(long millisecs) throws IOException
{
if (upgraded)
return super.blockWritable(millisecs);
else
return plainEndPoint.blockWritable(millisecs);
return _endp.blockWritable(millisecs);
}
public boolean isOpen()
{
if (upgraded)
return super.isOpen();
else
return plainEndPoint.isOpen();
return _endp.isOpen();
}
public Object getTransport()
{
if (upgraded)
return super.getTransport();
else
return plainEndPoint.getTransport();
}
public boolean isBufferingInput()
{
if (upgraded)
return super.isBufferingInput();
else
return plainEndPoint.isBufferingInput();
}
public boolean isBufferingOutput()
{
if (upgraded)
return super.isBufferingOutput();
else
return plainEndPoint.isBufferingOutput();
return _endp.getTransport();
}
public void flush() throws IOException
{
if (upgraded)
super.flush();
else
plainEndPoint.flush();
_endp.flush();
}
public int getMaxIdleTime()
{
if (upgraded)
return super.getMaxIdleTime();
else
return plainEndPoint.getMaxIdleTime();
return _endp.getMaxIdleTime();
}
public void setMaxIdleTime(int timeMs) throws IOException
{
if (upgraded)
super.setMaxIdleTime(timeMs);
else
plainEndPoint.setMaxIdleTime(timeMs);
_endp.setMaxIdleTime(timeMs);
}
public void onIdleExpired()
{
_endp.onIdleExpired();
}
public void setCheckForIdle(boolean check)
{
_endp.setCheckForIdle(check);
}
public boolean isCheckForIdle()
{
return _endp.isCheckForIdle();
}
public String toString()
{
return "Upgradable:"+_endp.toString();
}
}
}

View File

@ -17,7 +17,6 @@ import java.io.InterruptedIOException;
import java.net.Socket;
import javax.net.SocketFactory;
import javax.net.ssl.SSLContext;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
@ -55,9 +54,9 @@ class SocketConnector extends AbstractLifeCycle implements HttpClient.Connector
Address address = destination.isProxied() ? destination.getProxy() : destination.getAddress();
socket.connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
EndPoint endpoint=new SocketEndPoint(socket);
final EndPoint endpoint=new SocketEndPoint(socket);
final HttpConnection connection=new HttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint);
final AbstractHttpConnection connection=new BlockingHttpConnection(_httpClient.getRequestBuffers(),_httpClient.getResponseBuffers(),endpoint);
connection.setDestination(destination);
destination.onNewConnection(connection);
_httpClient.getThreadPool().dispatch(new Runnable()

View File

@ -14,7 +14,11 @@
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
@ -25,9 +29,6 @@ import java.util.concurrent.TimeUnit;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* @version $Revision$ $Date$
*/
@ -41,6 +42,14 @@ public abstract class AbstractConnectionTest
return httpClient;
}
protected ServerSocket newServerSocket() throws IOException
{
ServerSocket serverSocket=new ServerSocket();
serverSocket.bind(null);
return serverSocket;
}
@Test
public void testServerClosedConnection() throws Exception
{
@ -119,11 +128,15 @@ public abstract class AbstractConnectionTest
}
}
protected String getScheme()
{
return "http";
}
@Test
public void testServerClosedIncomplete() throws Exception
{
ServerSocket serverSocket = new ServerSocket();
serverSocket.bind(null);
ServerSocket serverSocket = newServerSocket();
int port=serverSocket.getLocalPort();
HttpClient httpClient = newHttpClient();
@ -133,6 +146,7 @@ public abstract class AbstractConnectionTest
{
CountDownLatch latch = new CountDownLatch(1);
HttpExchange exchange = new ConnectionExchange(latch);
exchange.setScheme(getScheme());
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
@ -159,7 +173,9 @@ public abstract class AbstractConnectionTest
remote.close();
assertEquals(HttpExchange.STATUS_EXCEPTED, exchange.waitForDone());
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_EXCEPTED, status);
}
finally
@ -346,27 +362,33 @@ public abstract class AbstractConnectionTest
HttpDestination dest = httpClient.getDestination(new Address("localhost", port),false);
httpClient.send(exchange);
Socket s = serverSocket.accept();
Socket server = serverSocket.accept();
server.setSoTimeout(5000);
byte[] buf = new byte[4096];
s.getInputStream().read(buf);
int len=server.getInputStream().read(buf);
assertEquals(1,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
s.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes());
server.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes());
Thread.sleep(300);
assertEquals(HttpExchange.STATUS_COMPLETED,exchange.waitForDone());
Thread.sleep(200); // TODO get rid of this
assertEquals(1,dest.getConnections());
assertEquals(1,dest.getIdleConnections());
exchange = new ConnectionExchange();
exchange.setAddress(new Address("localhost", port));
exchange.setRequestURI("/");
httpClient.send(exchange);
s.getInputStream().read(buf);
assertEquals(1,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
s.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes());
len=server.getInputStream().read(buf);
assertEquals(1,dest.getConnections());
assertEquals(0,dest.getIdleConnections());
server.getOutputStream().write("HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n".getBytes());
Thread.sleep(500);

View File

@ -14,7 +14,11 @@
package org.eclipse.jetty.client;
import static org.junit.Assert.*;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.SocketTimeoutException;
@ -25,23 +29,25 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConnection;
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.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;
import org.junit.Test;
/**
* @version $Revision$ $Date$
*/
public abstract class AbstractHttpExchangeCancelTest
{
private static final Logger LOG = Log.getLogger(AbstractHttpExchangeCancelTest.TestHttpExchange.class);
private Server server;
private Connector connector;
@ -73,13 +79,13 @@ public abstract class AbstractHttpExchangeCancelTest
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
void setStatus(int status)
boolean setStatus(int status)
{
// Cancel before setting the new status
if (getStatus() == HttpExchange.STATUS_START &&
status == STATUS_WAITING_FOR_CONNECTION)
cancel();
super.setStatus(status);
return super.setStatus(status);
}
};
exchange.setAddress(newAddress());
@ -110,14 +116,15 @@ public abstract class AbstractHttpExchangeCancelTest
TestHttpExchange exchange = new TestHttpExchange()
{
@Override
void setStatus(int status)
boolean setStatus(int status)
{
// Cancel after setting the new status
int oldStatus = getStatus();
super.setStatus(status);
boolean set = super.setStatus(status);
if (oldStatus == STATUS_START &&
getStatus() == HttpExchange.STATUS_WAITING_FOR_CONNECTION)
cancel();
return set;
}
};
exchange.setAddress(newAddress());
@ -181,10 +188,10 @@ public abstract class AbstractHttpExchangeCancelTest
getHttpClient().send(exchange);
int status = exchange.waitForDone();
assertEquals(HttpExchange.STATUS_CANCELLED, status);
assertFalse(exchange.isResponseCompleted());
assertFalse(exchange.isFailed());
assertFalse(exchange.isAssociated());
assertThat("Exchange Status", status, is(HttpExchange.STATUS_CANCELLED));
assertThat("Exchange.isResponseCompleted", exchange.isResponseCompleted(), is(false));
assertThat("Exchange.isFailed", exchange.isFailed(), is(false));
assertThat("Exchange.isAssociated", exchange.isAssociated(), is(false));
}
/* ------------------------------------------------------------ */
@ -318,7 +325,7 @@ public abstract class AbstractHttpExchangeCancelTest
{
try
{
((StdErrLog)Log.getLogger(HttpConnection.class)).setHideStacks(true);
((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(true);
TestHttpExchange exchange = new TestHttpExchange();
exchange.setAddress(newAddress());
exchange.setRequestURI("/?action=throw");
@ -333,7 +340,7 @@ public abstract class AbstractHttpExchangeCancelTest
}
finally
{
((StdErrLog)Log.getLogger(HttpConnection.class)).setHideStacks(false);
((StdErrLog)Log.getLogger(AbstractHttpConnection.class)).setHideStacks(false);
}
}
@ -442,6 +449,7 @@ public abstract class AbstractHttpExchangeCancelTest
@Override
protected synchronized void onException(Throwable ex)
{
LOG.debug(ex);
if (ex instanceof SocketTimeoutException ||
ex.getCause() instanceof SocketTimeoutException)
expired=true;

View File

@ -13,6 +13,13 @@
package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.ServerSocket;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.BeforeClass;
public class AsyncSelectConnectionTest extends AbstractConnectionTest
{
protected HttpClient newHttpClient()
@ -23,10 +30,38 @@ public class AsyncSelectConnectionTest extends AbstractConnectionTest
return httpClient;
}
static SslContextFactory ctx = new SslContextFactory(MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath());
@BeforeClass
public static void initKS() throws Exception
{
ctx.setKeyStorePassword("storepwd");
ctx.setKeyManagerPassword("keypwd");
ctx.start();
}
@Override
protected String getScheme()
{
return "https";
}
@Override
protected ServerSocket newServerSocket() throws IOException
{
return ctx.newSslServerSocket(null,0,100);
}
@Override
public void testServerHalfClosedIncomplete() throws Exception
{
super.testServerHalfClosedIncomplete();
// SSL doesn't do half closes
}
@Override
public void testServerClosedIncomplete() throws Exception
{
super.testServerClosedIncomplete();
}

View File

@ -16,7 +16,6 @@ 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
@ -32,4 +31,18 @@ public class AsyncSslHttpExchangeTest extends SslHttpExchangeTest
_port = _server.getConnectors()[0].getLocalPort();
}
@Test
public void testPerf1() throws Exception
{
sender(1,true);
}
@Override
public void testBigPostWithContentExchange() throws Exception
{
super.testBigPostWithContentExchange();
}
}

View File

@ -33,11 +33,26 @@ public class Curl
client.start();
boolean async=true;
boolean dump= false;
boolean verbose= false;
final CountDownLatch latch = new CountDownLatch(args.length);
int urls=0;
for (String arg : args)
{
if (!arg.startsWith("-"))
urls++;
}
final CountDownLatch latch = new CountDownLatch(urls);
for (String arg : args)
{
if ("--verbose".equals(arg))
{
verbose=true;
continue;
}
if ("--sync".equals(arg))
{
async=false;
@ -63,6 +78,7 @@ public class Curl
}
final boolean d = dump;
final boolean v = verbose;
HttpExchange ex = new HttpExchange()
{
AtomicBoolean counted=new AtomicBoolean(false);
@ -105,6 +121,7 @@ public class Curl
super.onResponseContent(content);
if (d)
System.out.print(content.toString());
if (v)
System.err.println("got "+content.length());
}
@ -116,6 +133,7 @@ public class Curl
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
super.onResponseHeader(name,value);
if (v)
System.err.println(name+": "+value);
}
@ -127,6 +145,7 @@ public class Curl
protected void onResponseHeaderComplete() throws IOException
{
super.onResponseHeaderComplete();
if (v)
System.err.println();
}
@ -138,6 +157,7 @@ public class Curl
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
super.onResponseStatus(version,status,reason);
if (v)
System.err.println(version+" "+status+" "+reason);
}
};

View File

@ -16,8 +16,6 @@ package org.eclipse.jetty.client;
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
{
@ -31,12 +29,4 @@ public class ExternalKeyStoreAsyncSslHttpExchangeTest extends SslHttpExchangeTes
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
_port = _server.getConnectors()[0].getLocalPort();
}
@Override
@Test
public void testBigPostWithContentExchange() throws Exception
{
super.testBigPostWithContentExchange();
}
}

View File

@ -13,8 +13,12 @@
package org.eclipse.jetty.client;
import static org.junit.Assert.*;
import static org.junit.matchers.JUnitMatchers.*;
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 java.io.IOException;
import java.io.InputStream;
@ -40,9 +44,7 @@ import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.toolchain.test.Stress;
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;
/* ------------------------------------------------------------ */
@ -51,7 +53,7 @@ import org.junit.Test;
*/
public class HttpExchangeTest
{
final static boolean verbose=false;
final static boolean verbose=HttpExchange.LOG.isDebugEnabled();
protected static int _maxConnectionsPerAddress = 2;
protected static String _scheme = "http";
protected static Server _server;
@ -125,6 +127,7 @@ public class HttpExchangeTest
*/
public void sender(final int nb, final boolean close) throws Exception
{
// System.err.printf("%nSENDER %d %s%n",nb,close);
_count.set(0);
final CountDownLatch complete = new CountDownLatch(nb);
final AtomicInteger allcontent = new AtomicInteger(nb);
@ -144,7 +147,7 @@ public class HttpExchangeTest
protected void onRequestCommitted()
{
if (verbose)
System.err.println("[ ");
System.err.println(n+" [ "+this);
result = "committed";
}
@ -153,7 +156,7 @@ public class HttpExchangeTest
protected void onRequestComplete() throws IOException
{
if (verbose)
System.err.println("[ ==");
System.err.println(n+" [ ==");
result = "sent";
}
@ -162,7 +165,7 @@ public class HttpExchangeTest
protected void onResponseStatus(Buffer version, int status, Buffer reason)
{
if (verbose)
System.err.println("] "+version+" "+status+" "+reason);
System.err.println(n+" ] "+version+" "+status+" "+reason);
result = "status";
}
@ -171,7 +174,7 @@ public class HttpExchangeTest
protected void onResponseHeader(Buffer name, Buffer value)
{
if (verbose)
System.err.println("] "+name+": "+value);
System.err.println(n+" ] "+name+": "+value);
}
/* ------------------------------------------------------------ */
@ -179,7 +182,7 @@ public class HttpExchangeTest
protected void onResponseHeaderComplete() throws IOException
{
if (verbose)
System.err.println("] -");
System.err.println(n+" ] -");
result = "content";
super.onResponseHeaderComplete();
}
@ -190,7 +193,7 @@ public class HttpExchangeTest
{
len += content.length();
if (verbose)
System.err.println("] "+content.length()+" -> "+len);
System.err.println(n+" ] "+content.length()+" -> "+len);
}
/* ------------------------------------------------------------ */
@ -198,12 +201,12 @@ public class HttpExchangeTest
protected void onResponseComplete()
{
if (verbose)
System.err.println("] == "+len+" "+complete.getCount()+"/"+nb);
System.err.println(n+" ] == "+len+" "+complete.getCount()+"/"+nb);
result = "complete";
if (len == 2009)
allcontent.decrementAndGet();
else
System.err.println(n + " ONLY " + len+ "/2009");
System.err.println(n+ " ONLY " + len+ "/2009");
complete.countDown();
}
@ -212,10 +215,10 @@ public class HttpExchangeTest
protected void onConnectionFailed(Throwable ex)
{
if (verbose)
System.err.println("] "+ex);
System.err.println(n+" ] "+ex);
complete.countDown();
result = "failed";
System.err.println(n + " FAILED " + ex);
System.err.println(n+ " FAILED " + ex);
super.onConnectionFailed(ex);
}
@ -224,10 +227,10 @@ public class HttpExchangeTest
protected void onException(Throwable ex)
{
if (verbose)
System.err.println("] "+ex);
System.err.println(n+" ] "+ex);
complete.countDown();
result = "excepted";
System.err.println(n + " EXCEPTED " + ex);
System.err.println(n+ " EXCEPTED " + ex);
super.onException(ex);
}
@ -236,7 +239,7 @@ public class HttpExchangeTest
protected void onExpire()
{
if (verbose)
System.err.println("] expired");
System.err.println(n+" ] expired");
complete.countDown();
result = "expired";
System.err.println(n + " EXPIRED " + len);
@ -452,8 +455,23 @@ public class HttpExchangeTest
httpExchange.setMethod(HttpMethods.POST);
httpExchange.setRequestContentType("application/data");
httpExchange.setRequestContent(babuf);
_httpClient.send(httpExchange);
long start=System.currentTimeMillis();
while(!httpExchange.isDone())
{
long now=System.currentTimeMillis();
if ((now-start)>=10000)
{
System.err.println("TEST IS TAKING TOOOOO LONG!!!!!!!!!!!!!!!!!!!!");
System.err.println("CLIENT:");
System.err.println(_httpClient.dump());
System.err.println("SERVER:");
_server.dumpStdErr();
break;
}
Thread.sleep(100);
}
int status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED,status);
String result=httpExchange.getResponseContent();
@ -465,6 +483,22 @@ public class HttpExchangeTest
httpExchange.setRequestContentType("application/data");
httpExchange.setRequestContent(niobuf);
_httpClient.send(httpExchange);
start=System.currentTimeMillis();
while(!httpExchange.isDone())
{
long now=System.currentTimeMillis();
if ((now-start)>=10000)
{
System.err.println("TEST IS TAKING TOOOOO LONG!!!!!!!!!!!!!!!!!!!!");
System.err.println("CLIENT:");
System.err.println(_httpClient.dump());
System.err.println("SERVER:");
_server.dumpStdErr();
break;
}
Thread.sleep(100);
}
status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
result=httpExchange.getResponseContent();
@ -475,10 +509,7 @@ public class HttpExchangeTest
@Test
public void testSlowPost() throws Exception
{
ContentExchange httpExchange=new ContentExchange()
{
};
ContentExchange httpExchange=new ContentExchange();
httpExchange.setURI(getBaseURI());
httpExchange.setMethod(HttpMethods.POST);
@ -491,15 +522,27 @@ public class HttpExchangeTest
@Override
public int read() throws IOException
{
// System.err.printf("reading 1 of %d/%d%n",_index,data.length());
if (_index>=data.length())
return -1;
try
{
Thread.sleep(5);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
// System.err.printf("read 1%n");
return data.charAt(_index++);
}
@Override
public int read(byte[] b, int off, int len) throws IOException
{
// System.err.printf("reading %d of %d/%d%n",len,_index,data.length());
if (_index >= data.length())
return -1;
@ -516,18 +559,17 @@ public class HttpExchangeTest
while (l < 5 && _index < data.length() && l < len)
b[off + l++] = (byte)data.charAt(_index++);
// System.err.printf("read %d%n",l);
return l;
}
};
httpExchange.setRequestContentSource(content);
// httpExchange.setRequestContent(new ByteArrayBuffer(data));
_httpClient.send(httpExchange);
int status = httpExchange.waitForDone();
// httpExchange.waitForStatus(HttpExchange.STATUS_COMPLETED);
String result = httpExchange.getResponseContent();
assertEquals(HttpExchange.STATUS_COMPLETED,status);
assertEquals(data,result);
@ -571,7 +613,7 @@ public class HttpExchangeTest
{
_httpClient = serverAndClientCreator.createClient(3000L,3500L,2000);
final HttpDestination destination = _httpClient.getDestination(new Address("localhost",_port),_scheme.equalsIgnoreCase("https"));
final org.eclipse.jetty.client.HttpConnection[] connections = new org.eclipse.jetty.client.HttpConnection[_maxConnectionsPerAddress];
final org.eclipse.jetty.client.AbstractHttpConnection[] connections = new org.eclipse.jetty.client.AbstractHttpConnection[_maxConnectionsPerAddress];
for (int i = 0; i < _maxConnectionsPerAddress; i++)
{
connections[i] = destination.reserveConnection(200);
@ -595,7 +637,7 @@ public class HttpExchangeTest
assertNotNull(c);
// release connections
for (HttpConnection httpConnection : connections){
for (AbstractHttpConnection httpConnection : connections){
destination.returnConnection(httpConnection,false);
}
}

View File

@ -0,0 +1,136 @@
// ========================================================================
// 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;
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.net.ProtocolException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ConnectHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/* ------------------------------------------------------------ */
/**
* This UnitTest class executes two tests. Both will send a http request to https://google.com through a misbehaving proxy server.
* <p/>
* The first test runs against a proxy which simply closes the connection (as nginx does) for a connect request. The second proxy server always responds with a
* 500 error.
* <p/>
* The expected result for both tests is an exception and the HttpExchange should have status HttpExchange.STATUS_EXCEPTED.
*/
public class HttpsViaBrokenHttpProxyTest
{
private Server _proxy = new Server();
private HttpClient _client = new HttpClient();
@Before
public void init() throws Exception
{
// setup proxies with different behaviour
_proxy.addConnector(new SelectChannelConnector());
_proxy.setHandler(new BadBehavingConnectHandler());
_proxy.start();
int proxyClosingConnectionPort = _proxy.getConnectors()[0].getLocalPort();
_client.setProxy(new Address("localhost", proxyClosingConnectionPort));
_client.start();
}
@After
public void destroy() throws Exception
{
_client.stop();
_proxy.stop();
}
@Test
public void httpsViaProxyThatClosesConnectionOnConnectRequestTest() throws Exception
{
sendRequestThroughProxy(new ContentExchange()
{
@Override
protected void onException(Throwable x)
{
}
}, "close", 9);
}
@Test
public void httpsViaProxyThatReturns500ErrorTest() throws Exception
{
HttpExchange exchange = new ContentExchange()
{
@Override
protected void onException(Throwable x)
{
// Suppress logging for expected exception
if (!(x instanceof ProtocolException))
super.onException(x);
}
};
sendRequestThroughProxy(exchange, "error500", 9);
}
@Test
public void httpsViaProxyThatReturns504ErrorTest() throws Exception
{
sendRequestThroughProxy(new ContentExchange(), "error504", 8);
}
private void sendRequestThroughProxy(HttpExchange exchange, String desiredBehaviour, int exptectedStatus) throws Exception
{
String url = "https://" + desiredBehaviour + ".com/";
exchange.setURL(url);
exchange.addRequestHeader("behaviour", desiredBehaviour);
_client.send(exchange);
assertEquals(HttpExchange.toState(exptectedStatus) + " status awaited", exptectedStatus, exchange.waitForDone());
}
private class BadBehavingConnectHandler extends ConnectHandler
{
@Override
protected void handleConnect(Request baseRequest, HttpServletRequest request, HttpServletResponse response, String serverAddress)
throws ServletException, IOException
{
if (serverAddress.contains("close"))
{
AbstractHttpConnection.getCurrentConnection().getEndPoint().close();
}
else if (serverAddress.contains("error500"))
{
response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500);
}
else if (serverAddress.contains("error504"))
{
response.setStatus(HttpStatus.GATEWAY_TIMEOUT_504);
}
baseRequest.setHandled(true);
}
}
}

View File

@ -51,4 +51,10 @@ public class NonBlockingHttpExchangeCancelTest extends AbstractHttpExchangeCance
{
return httpClient;
}
/* ------------------------------------------------------------ */
public void testHttpExchangeCancelOnRequestComplete() throws Exception
{
super.testHttpExchangeCancelOnRequestComplete();
}
}

View File

@ -1,9 +1,13 @@
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
@ -12,7 +16,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
@ -23,12 +26,10 @@ import org.eclipse.jetty.server.handler.ConnectHandler;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.After;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class ProxyTunnellingTest
{
private Server server;
@ -217,7 +218,7 @@ public class ProxyTunnellingTest
ContentExchange exchange = new ContentExchange(true)
{
@Override
protected void onConnectionFailed(Throwable x)
protected void onException(Throwable x)
{
latch.countDown();
}

View File

@ -19,7 +19,6 @@ import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
@ -33,6 +32,7 @@ import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
public class SecuredContentExchangeTest
extends ContentExchangeTest

View File

@ -20,7 +20,6 @@ import java.util.Set;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
@ -34,6 +33,7 @@ import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
import org.junit.Test;
public class SecuredErrorStatusTest

View File

@ -31,7 +31,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.client.security.SimpleRealmResolver;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.security.ConstraintMapping;
@ -46,6 +45,7 @@ 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.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

View File

@ -0,0 +1,211 @@
package org.eclipse.jetty.client;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
/* ------------------------------------------------------------ */
/**
*/
public class Siege
{
private static final class ConcurrentExchange extends HttpExchange
{
private final long _start=System.currentTimeMillis();
private final HttpClient _client;
private final CountDownLatch _latch;
volatile int _status;
volatile int _count;
volatile long _bytes;
final List<String> _uris;
final int _repeats;
int _u;
int _r;
AtomicBoolean counted=new AtomicBoolean(false);
public ConcurrentExchange(HttpClient client,CountDownLatch latch, List<String> uris, int repeats)
{
_client = client;
_latch = latch;
_uris = uris;
_repeats = repeats;
}
@Override
protected void onConnectionFailed(Throwable ex)
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onConnectionFailed(ex);
}
@Override
protected void onException(Throwable ex)
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onException(ex);
}
@Override
protected void onExpire()
{
if (!counted.getAndSet(true))
_latch.countDown();
super.onExpire();
}
@Override
protected void onResponseComplete() throws IOException
{
if (_status==200)
_count++;
if (!next() && !counted.getAndSet(true))
{
_latch.countDown();
long duration=System.currentTimeMillis()-_start;
System.err.printf("Got %d/%d with %dB in %dms %d%n",_count,_uris.size()*_repeats,_bytes,duration,_latch.getCount());
}
}
/* ------------------------------------------------------------ */
@Override
protected void onResponseContent(Buffer content) throws IOException
{
_bytes+=content.length();
super.onResponseContent(content);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeader(org.eclipse.jetty.io.Buffer, org.eclipse.jetty.io.Buffer)
*/
@Override
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
super.onResponseHeader(name,value);
if ("Set-Cookie".equalsIgnoreCase(name.toString()))
{
String v=value.toString();
int c = v.indexOf(';');
if (c>=0)
v=v.substring(0,c);
addRequestHeader("Cookie",v);
}
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseHeaderComplete()
*/
@Override
protected void onResponseHeaderComplete() throws IOException
{
super.onResponseHeaderComplete();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.Buffer, int, org.eclipse.jetty.io.Buffer)
*/
@Override
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
_status=status;
super.onResponseStatus(version,status,reason);
}
public boolean next()
{
if (_u>=_uris.size())
{
_u=0;
_r++;
if (_r>=_repeats)
return false;
}
String uri=_uris.get(_u++);
reset();
setMethod(HttpMethods.GET);
setURL(uri);
try
{
_client.send(this);
}
catch(IOException e)
{
e.printStackTrace();
return false;
}
return true;
}
}
public static void main(String[] args)
throws Exception
{
if (args.length==0)
args=new String[]
{ "-c", "2", "-r", "2", "http://localhost:8080/dump", "http://localhost:8080/d.txt"};
int concurrent=1;
int repeats=1;
final List<String> uris = new ArrayList<String>();
for (int i=0; i<args.length; i++)
{
String arg=args[i];
if ("-c".equals(arg))
{
concurrent=Integer.parseInt(args[++i]);
continue;
}
if ("-r".equals(arg))
{
repeats=Integer.parseInt(args[++i]);
continue;
}
uris.add(arg);
}
QueuedThreadPool pool = new QueuedThreadPool();
pool.setMaxThreads(500);
pool.setDaemon(true);
HttpClient client = new HttpClient();
client.setThreadPool(pool);
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setIdleTimeout(30000);
client.setConnectTimeout(30000);
client.setMaxConnectionsPerAddress(concurrent*2);
client.start();
final CountDownLatch latch = new CountDownLatch(concurrent);
for (int i=0;i<concurrent;i++)
{
ConcurrentExchange ex = new ConcurrentExchange(client,latch,uris,repeats);
if (!ex.next())
latch.countDown();
}
latch.await();
client.stop();
pool.stop();
}
}

View File

@ -0,0 +1,246 @@
package org.eclipse.jetty.client;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.eclipse.jetty.http.HttpHeaderValues;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.bio.SocketConnector;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.junit.Test;
/**
* A class that attempts to simulate a client communicating with a slow server. It imposes a delay between each handle() call made to the server's handler.
*
* The client sends a binary blob of data to the server, and this blob is then inspected to verify correct transfer.
*/
public class SluggishServerTest
{
/** msec to wait between reads in the handler -- may need to adjust based on OS/HW/etc. to reproduce bug */
private final static int READ_DELAY = 5;
private final static String URL = "http://localhost:";
/** Stream providing a binary message to send */
private static class SluggishStream extends InputStream
{
private final byte[] request;
private int pos;
public SluggishStream(byte[] request)
{
this.request = request;
this.pos = 0;
}
@Override
public int read() throws IOException
{
if (pos < request.length)
{
int byteVal = request[pos++] & 0xFF;
return byteVal;
}
else
{
return -1;
}
}
}
/** Sends a message containing random binary content to a SluggishHandler */
private static class SluggishExchange extends HttpExchange
{
private byte[] request;
public SluggishExchange(int port, int count)
{
request = new byte[count];
for (int i=0;i<count;i++)
request[i]=(byte)('A'+(i%26));
setURL(URL+port);
setRequestContentSource(new SluggishStream(request));
setRequestContentType("application/octet-stream");
setRequestHeader(HttpHeaders.TRANSFER_ENCODING,HttpHeaderValues.CHUNKED);
}
public byte[] getRequestBody()
{
return request;
}
@Override
protected void onRequestComplete()
{
//System.err.println("REQUEST COMPLETE " + this);
}
@Override
protected void onResponseComplete()
{
//System.err.println("RESPONSE COMPLETE " + this);
}
@Override
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
{
//System.err.printf("<<< %s %d %s%n",version,status,reason);
super.onResponseStatus(version,status,reason);
}
@Override
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
{
//System.err.printf("<<< %s: %s%n",name,value);
super.onResponseHeader(name,value);
}
@Override
protected void onResponseHeaderComplete() throws IOException
{
//System.err.printf("<<< --%n");
super.onResponseHeaderComplete();
}
}
/** Receives binary message from a SluggishExchange & stores it for validation */
private static class SluggishHandler extends AbstractHandler
{
private final ArrayList<Byte> accumulatedRequest;
public SluggishHandler(int requestSize)
{
accumulatedRequest = new ArrayList<Byte>(requestSize);
}
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
accumulatedRequest.clear();
ServletInputStream input = request.getInputStream();
byte[] buffer = new byte[16384];
int bytesAvailable;
while ((bytesAvailable = input.read(buffer,0,buffer.length)) > 0)
{
//System.err.println("AVAILABLE FOR READ = " + bytesAvailable);
for (int n = 0; n < bytesAvailable; ++n)
{
accumulatedRequest.add(buffer[n]);
}
try
{
Thread.sleep(READ_DELAY);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
//System.err.println("HANDLED");
}
public byte[] getAccumulatedRequest()
{
byte[] buffer = new byte[accumulatedRequest.size()];
int pos = 0;
for (Byte b : accumulatedRequest)
{
buffer[pos++] = b;
}
return buffer;
}
}
private static boolean compareBuffers(byte[] sent, byte[] received)
{
if (sent.length != received.length)
{
System.err.format("Mismatch in sent/received lengths: sent=%d received=%d\n",sent.length,received.length);
return false;
}
else
{
for (int n = 0; n < sent.length; ++n)
{
if (sent[n] != received[n])
{
System.err.format("Mismatch at offset %d: request=%d response=%d\n",n,sent[n],received[n]);
return false;
}
}
}
return true;
}
@Test
public void test0() throws Exception
{
goSlow(20000,10);
}
@Test
public void test1() throws Exception
{
goSlow(200000,5);
}
@Test
public void test2() throws Exception
{
goSlow(2000000,2);
}
void goSlow(int requestSize,int iterations) throws Exception
{
Server server = new Server();
SocketConnector connector = new SocketConnector();
server.addConnector(connector);
SluggishHandler handler = new SluggishHandler(requestSize);
server.setHandler(handler);
server.start();
int port = connector.getLocalPort();
HttpClient client = new HttpClient();
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
client.setConnectTimeout(5000);
client.setIdleTimeout(60000);
client.start();
try
{
for (int i = 0; i < iterations; ++i)
{
//System.err.format("-------------- ITERATION %d ------------------\n",i);
SluggishExchange exchange = new SluggishExchange(port,requestSize);
long startTime = System.currentTimeMillis();
client.send(exchange);
exchange.waitForDone();
long endTime = System.currentTimeMillis();
//System.err.println("EXCHANGE STATUS = " + exchange);
//System.err.println("ELAPSED MSEC = " + (endTime - startTime));
Assert.assertTrue(compareBuffers(exchange.getRequestBody(),handler.getAccumulatedRequest()));
}
}
finally
{
server.stop();
server.join();
}
}
}

View File

@ -13,6 +13,8 @@
package org.eclipse.jetty.client;
import static org.junit.Assert.assertEquals;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
@ -21,8 +23,6 @@ import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import static org.junit.Assert.assertEquals;
public class SocketConnectionTest extends AbstractConnectionTest
{
protected HttpClient newHttpClient()
@ -88,4 +88,9 @@ public class SocketConnectionTest extends AbstractConnectionTest
httpClient.stop();
}
}
public void testIdleConnection() throws Exception
{
super.testIdleConnection();
}
}

View File

@ -0,0 +1,148 @@
package org.eclipse.jetty.client;
import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
public class SslBytesClientTest extends SslBytesTest
{
private ExecutorService threadPool;
private HttpClient client;
private SimpleProxy proxy;
private SSLServerSocket acceptor;
@Before
public void init() throws Exception
{
threadPool = Executors.newCachedThreadPool();
client = new HttpClient();
client.setMaxConnectionsPerAddress(1);
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
File keyStore = MavenTestingUtils.getTestResourceFile("keystore");
SslContextFactory cf = client.getSslContextFactory();
cf.setKeyStorePath(keyStore.getAbsolutePath());
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
client.start();
SSLContext sslContext = cf.getSslContext();
acceptor = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket(0);
int serverPort = acceptor.getLocalPort();
proxy = new SimpleProxy(threadPool, "localhost", serverPort);
proxy.start();
logger.debug(":{} <==> :{}", proxy.getPort(), serverPort);
}
@After
public void destroy() throws Exception
{
if (acceptor != null)
acceptor.close();
if (proxy != null)
proxy.stop();
if (client != null)
client.stop();
if (threadPool != null)
threadPool.shutdownNow();
}
@Test
public void testHandshake() throws Exception
{
ContentExchange exchange = new ContentExchange(true);
exchange.setURL("https://localhost:" + proxy.getPort());
String method = HttpMethods.GET;
exchange.setMethod(method);
client.send(exchange);
Assert.assertTrue(proxy.awaitClient(5, TimeUnit.SECONDS));
final SSLSocket server = (SSLSocket)acceptor.accept();
server.setUseClientMode(false);
Future<Object> handshake = threadPool.submit(new Callable<Object>()
{
public Object call() throws Exception
{
server.startHandshake();
return null;
}
});
// Client Hello
TLSRecord record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToServer(record);
// Server Hello + Certificate + Server Done
record = proxy.readFromServer();
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToClient(record);
// Client Key Exchange
record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToServer(record);
// Change Cipher Spec
record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType());
proxy.flushToServer(record);
// Client Done
record = proxy.readFromClient();
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToServer(record);
// Change Cipher Spec
record = proxy.readFromServer();
Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType());
proxy.flushToClient(record);
// Server Done
record = proxy.readFromServer();
Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
proxy.flushToClient(record);
Assert.assertNull(handshake.get(5, TimeUnit.SECONDS));
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
// Read request
BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream(), "UTF-8"));
String line = reader.readLine();
Assert.assertTrue(line.startsWith(method));
while (line.length() > 0)
line = reader.readLine();
// Write response
OutputStream output = server.getOutputStream();
output.write(("HTTP/1.1 200 OK\r\n" +
"Content-Length: 0\r\n" +
"\r\n").getBytes("UTF-8"));
output.flush();
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
Assert.assertEquals(HttpStatus.OK_200, exchange.getResponseStatus());
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,337 @@
package org.eclipse.jetty.client;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.junit.Assert;
public abstract class SslBytesTest
{
protected final Logger logger = Log.getLogger(getClass());
public static class TLSRecord
{
private final SslBytesServerTest.TLSRecord.Type type;
private final byte[] bytes;
public TLSRecord(SslBytesServerTest.TLSRecord.Type type, byte[] bytes)
{
this.type = type;
this.bytes = bytes;
}
public SslBytesServerTest.TLSRecord.Type getType()
{
return type;
}
public byte[] getBytes()
{
return bytes;
}
@Override
public String toString()
{
return "TLSRecord [" + type + "] " + bytes.length + " bytes";
}
public enum Type
{
CHANGE_CIPHER_SPEC(20), ALERT(21), HANDSHAKE(22), APPLICATION(23);
private int code;
private Type(int code)
{
this.code = code;
SslBytesServerTest.TLSRecord.Type.Mapper.codes.put(this.code, this);
}
public static SslBytesServerTest.TLSRecord.Type from(int code)
{
SslBytesServerTest.TLSRecord.Type result = SslBytesServerTest.TLSRecord.Type.Mapper.codes.get(code);
if (result == null)
throw new IllegalArgumentException("Invalid TLSRecord.Type " + code);
return result;
}
private static class Mapper
{
private static final Map<Integer, SslBytesServerTest.TLSRecord.Type> codes = new HashMap<Integer, SslBytesServerTest.TLSRecord.Type>();
}
}
}
public class SimpleProxy implements Runnable
{
private final CountDownLatch latch = new CountDownLatch(1);
private final ExecutorService threadPool;
private final String serverHost;
private final int serverPort;
private volatile ServerSocket serverSocket;
private volatile Socket server;
private volatile Socket client;
public SimpleProxy(ExecutorService threadPool, String serverHost, int serverPort)
{
this.threadPool = threadPool;
this.serverHost = serverHost;
this.serverPort = serverPort;
}
public void start() throws Exception
{
// serverSocket = new ServerSocket(5871);
serverSocket = new ServerSocket(0);
Thread acceptor = new Thread(this);
acceptor.start();
server = new Socket(serverHost, serverPort);
}
public void stop() throws Exception
{
serverSocket.close();
}
public void run()
{
try
{
client = serverSocket.accept();
latch.countDown();
}
catch (IOException x)
{
x.printStackTrace();
}
}
public int getPort()
{
return serverSocket.getLocalPort();
}
public TLSRecord readFromClient() throws IOException
{
TLSRecord record = read(client);
logger.debug("C --> P {}", record);
return record;
}
private TLSRecord read(Socket socket) throws IOException
{
InputStream input = socket.getInputStream();
int first = -2;
while (true)
{
try
{
socket.setSoTimeout(500);
first = input.read();
break;
}
catch (SocketTimeoutException x)
{
if (Thread.currentThread().isInterrupted())
break;
}
}
if (first == -2)
throw new InterruptedIOException();
else if (first == -1)
return null;
if (first >= 0x80)
{
// SSLv2 Record
int hiLength = first & 0x3F;
int loLength = input.read();
int length = (hiLength << 8) + loLength;
byte[] bytes = new byte[2 + length];
bytes[0] = (byte)first;
bytes[1] = (byte)loLength;
return read(TLSRecord.Type.HANDSHAKE, input, bytes, 2, length);
}
else
{
// TLS Record
int major = input.read();
int minor = input.read();
int hiLength = input.read();
int loLength = input.read();
int length = (hiLength << 8) + loLength;
byte[] bytes = new byte[1 + 2 + 2 + length];
bytes[0] = (byte)first;
bytes[1] = (byte)major;
bytes[2] = (byte)minor;
bytes[3] = (byte)hiLength;
bytes[4] = (byte)loLength;
return read(TLSRecord.Type.from(first), input, bytes, 5, length);
}
}
private TLSRecord read(SslBytesServerTest.TLSRecord.Type type, InputStream input, byte[] bytes, int offset, int length) throws IOException
{
while (length > 0)
{
int read = input.read(bytes, offset, length);
if (read < 0)
throw new EOFException();
offset += read;
length -= read;
}
return new TLSRecord(type, bytes);
}
public void flushToServer(TLSRecord record) throws IOException
{
if (record == null)
{
server.shutdownOutput();
if (client.isOutputShutdown())
{
client.close();
server.close();
}
}
else
{
flush(server, record.getBytes());
}
}
public void flushToServer(byte... bytes) throws IOException
{
flush(server, bytes);
}
private void flush(Socket socket, byte... bytes) throws IOException
{
OutputStream output = socket.getOutputStream();
output.write(bytes);
output.flush();
}
public TLSRecord readFromServer() throws IOException
{
TLSRecord record = read(server);
logger.debug("P <-- S {}", record);
return record;
}
public void flushToClient(TLSRecord record) throws IOException
{
if (record == null)
{
client.shutdownOutput();
if (server.isOutputShutdown())
{
server.close();
client.close();
}
}
else
{
flush(client, record.getBytes());
}
}
public SslBytesServerTest.SimpleProxy.AutomaticFlow startAutomaticFlow() throws InterruptedException
{
final CountDownLatch startLatch = new CountDownLatch(2);
final CountDownLatch stopLatch = new CountDownLatch(2);
Future<Object> clientToServer = threadPool.submit(new Callable<Object>()
{
public Object call() throws Exception
{
startLatch.countDown();
logger.debug("Automatic flow C --> S started");
try
{
while (true)
{
flushToServer(readFromClient());
}
}
catch (InterruptedIOException x)
{
return null;
}
finally
{
stopLatch.countDown();
logger.debug("Automatic flow C --> S finished");
}
}
});
Future<Object> serverToClient = threadPool.submit(new Callable<Object>()
{
public Object call() throws Exception
{
startLatch.countDown();
logger.debug("Automatic flow C <-- S started");
try
{
while (true)
{
flushToClient(readFromServer());
}
}
catch (InterruptedIOException x)
{
return null;
}
finally
{
stopLatch.countDown();
logger.debug("Automatic flow C <-- S finished");
}
}
});
Assert.assertTrue(startLatch.await(5, TimeUnit.SECONDS));
return new SslBytesServerTest.SimpleProxy.AutomaticFlow(stopLatch, clientToServer, serverToClient);
}
public boolean awaitClient(int time, TimeUnit unit) throws InterruptedException
{
return latch.await(time, unit);
}
public class AutomaticFlow
{
private final CountDownLatch stopLatch;
private final Future<Object> clientToServer;
private final Future<Object> serverToClient;
public AutomaticFlow(CountDownLatch stopLatch, Future<Object> clientToServer, Future<Object> serverToClient)
{
this.stopLatch = stopLatch;
this.clientToServer = clientToServer;
this.serverToClient = serverToClient;
}
public boolean stop(long time, TimeUnit unit) throws InterruptedException
{
clientToServer.cancel(true);
serverToClient.cancel(true);
return stopLatch.await(time, unit);
}
}
}
}

View File

@ -20,9 +20,6 @@ import java.util.Set;
import javax.security.auth.Subject;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.http.security.Credential;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.IdentityService;
@ -38,6 +35,9 @@ import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Credential;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SslCertSecuredExchangeTest extends ContentExchangeTest
{

View File

@ -15,7 +15,6 @@ package org.eclipse.jetty.client;
import java.io.File;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
@ -24,6 +23,7 @@ import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SslContentExchangeTest
extends ContentExchangeTest

View File

@ -13,16 +13,14 @@
package org.eclipse.jetty.client;
import static org.hamcrest.Matchers.*;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import org.eclipse.jetty.client.helperClasses.ServerAndClientCreator;
import org.eclipse.jetty.client.helperClasses.SslServerAndClientCreator;
import org.eclipse.jetty.server.Connector;
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;
/**
@ -72,9 +70,6 @@ public class SslHttpExchangeTest extends HttpExchangeTest
@Override
public void testPerf() throws Exception
{
// TODO needs to be further investigated
Assume.assumeTrue(!OS.IS_OSX || Stress.isEnabled());
// TODO Resolve problems on IBM JVM https://bugs.eclipse.org/bugs/show_bug.cgi?id=304532
IgnoreTestOnBuggyIBM();
super.testPerf();

View File

@ -19,8 +19,6 @@ import java.util.HashSet;
import java.util.Set;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
@ -34,6 +32,8 @@ import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public class SslSecuredContentExchangeTest
extends ContentExchangeTest

View File

@ -20,7 +20,6 @@ import java.util.Set;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
import org.eclipse.jetty.security.HashLoginService;
@ -34,6 +33,7 @@ import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.Constraint;
import org.junit.Test;
/* ------------------------------------------------------------ */

View File

@ -34,8 +34,6 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.security.HashRealmResolver;
import org.eclipse.jetty.client.security.Realm;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.http.security.Constraint;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.security.ConstraintMapping;
import org.eclipse.jetty.security.ConstraintSecurityHandler;
@ -51,6 +49,8 @@ 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;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

View File

@ -6,7 +6,6 @@ import java.security.KeyStore;
import java.security.cert.CRL;
import java.util.Collection;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
@ -16,6 +15,7 @@ import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.security.CertificateUtils;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public abstract class SslValidationTestBase extends ContentExchangeTest
{

View File

@ -16,7 +16,6 @@ package org.eclipse.jetty.client;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -26,17 +25,17 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.io.EofException;
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.util.IO;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* Functional testing for HttpExchange.
@ -44,91 +43,71 @@ import org.eclipse.jetty.util.IO;
* @author Matthew Purland
* @author Greg Wilkins
*/
public class UnexpectedDataTest extends TestCase
public class UnexpectedDataTest
{
protected int _maxConnectionsPerAddress = 1;
protected String _scheme = "http://";
protected Server _server;
protected int _port;
protected HttpClient _httpClient;
protected Connector _connector;
protected AtomicInteger _count = new AtomicInteger();
private Server _server;
private int _port;
private HttpClient _httpClient;
private Connector _connector;
private AtomicInteger _count = new AtomicInteger();
protected void setUp() throws Exception
@Before
public void setUp() throws Exception
{
startServer();
_httpClient=new HttpClient();
_httpClient = new HttpClient();
_httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
_httpClient.setMaxConnectionsPerAddress(_maxConnectionsPerAddress);
_httpClient.setMaxConnectionsPerAddress(1);
_httpClient.start();
}
protected void tearDown() throws Exception
@After
public void tearDown() throws Exception
{
_httpClient.stop();
Thread.sleep(500);
stopServer();
}
@Test
public void testUnexpectedData() throws Exception
{
for (int i=0; i<4; i++)
for (int i = 0; i < 4; ++i)
{
final CountDownLatch done=new CountDownLatch(1);
ContentExchange httpExchange=new ContentExchange()
final CountDownLatch done = new CountDownLatch(1);
ContentExchange httpExchange = new ContentExchange()
{
protected void onResponseComplete() throws IOException
{
super.onResponseComplete();
done.countDown();
}
};
httpExchange.setURL(_scheme+"localhost:"+_port+"/?i="+i);
httpExchange.setURL("http://localhost:" + _port + "/?i=" + i);
httpExchange.setMethod(HttpMethods.GET);
_httpClient.send(httpExchange);
done.await(1,TimeUnit.SECONDS);
Assert.assertTrue(done.await(1000, TimeUnit.SECONDS));
int status = httpExchange.getStatus();
String result=httpExchange.getResponseContent();
assertEquals("i="+i,0,result.indexOf("<hello>"));
assertEquals("i="+i,result.length()-10,result.indexOf("</hello>"));
assertEquals(HttpExchange.STATUS_COMPLETED, status);
String result = httpExchange.getResponseContent();
Assert.assertEquals("i=" + i, 0, result.indexOf("<hello>"));
Assert.assertEquals("i=" + i, result.length() - 10, result.indexOf("</hello>"));
Assert.assertEquals(HttpExchange.STATUS_COMPLETED, status);
Thread.sleep(5);
}
}
public static void copyStream(InputStream in, OutputStream out)
{
try
{
byte[] buffer=new byte[1024];
int len;
while ((len=in.read(buffer))>=0)
{
out.write(buffer,0,len);
}
}
catch (EofException e)
{
System.err.println(e);
}
catch (IOException e)
{
e.printStackTrace();
// Give the client the time to read -1 from server before issuing the next request
// There is currently no simple way to be notified of connection closed.
Thread.sleep(500);
}
}
protected void newServer() throws Exception
{
_server=new Server();
_server = new Server();
_server.setGracefulShutdown(500);
_connector=new SelectChannelConnector();
_connector = new SelectChannelConnector();
_connector.setPort(0);
_server.setConnectors(new Connector[] { _connector });
_server.setConnectors(new Connector[]{_connector});
}
protected void startServer() throws Exception
@ -139,7 +118,7 @@ public class UnexpectedDataTest extends TestCase
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException
{
int i=0;
int i = 0;
try
{
baseRequest.setHandled(true);
@ -148,11 +127,11 @@ public class UnexpectedDataTest extends TestCase
if (request.getMethod().equalsIgnoreCase("GET"))
{
StringBuffer buffer = new StringBuffer();
StringBuilder buffer = new StringBuilder();
buffer.append("<hello>\r\n");
for (; i<100; i++)
for (; i < 100; i++)
{
buffer.append(" <world>"+i+"</world>\r\n");
buffer.append(" <world>").append(i).append("</world>\r\n");
}
buffer.append("</hello>\r\n");
@ -169,35 +148,30 @@ public class UnexpectedDataTest extends TestCase
else
{
response.setContentType(request.getContentType());
int size=request.getContentLength();
ByteArrayOutputStream bout = new ByteArrayOutputStream(size>0?size:32768);
IO.copy(request.getInputStream(),bout);
int size = request.getContentLength();
ByteArrayOutputStream bout = new ByteArrayOutputStream(size > 0 ? size : 32768);
IO.copy(request.getInputStream(), bout);
response.getOutputStream().write(bout.toByteArray());
}
}
catch(IOException e)
catch (IOException e)
{
e.printStackTrace();
throw e;
}
catch(Throwable e)
catch (Throwable e)
{
e.printStackTrace();
throw new ServletException(e);
}
finally
{
// System.err.println("HANDLED "+i);
}
}
});
_server.start();
_port=_connector.getLocalPort();
_port = _connector.getLocalPort();
}
private void stopServer() throws Exception
{
_server.stop();
}
}

View File

@ -162,8 +162,6 @@ public class WebSocketUpgradeTest
int status = httpExchange.waitForDone();
assertEquals(HttpExchange.STATUS_COMPLETED, status);
// System.err.println("results="+_results);
assertEquals("serverWS.onConnect", _results.poll(1,TimeUnit.SECONDS));
TestWebSocket serverWS = (TestWebSocket)_results.poll(1,TimeUnit.SECONDS);

View File

@ -14,14 +14,13 @@
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;
import org.eclipse.jetty.util.ssl.SslContextFactory;
/* ------------------------------------------------------------ */
@ -35,7 +34,7 @@ public abstract class AbstractSslServerAndClientCreator implements ServerAndClie
public Server createServer() throws Exception
{
Server server = new Server();
//SslSelectChannelConnector connector = new SslSelectChannelConnector();
// SslSelectChannelConnector connector = new SslSelectChannelConnector();
SslSocketConnector connector = new SslSocketConnector();
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
@ -45,7 +44,6 @@ public abstract class AbstractSslServerAndClientCreator implements ServerAndClie
cf.setKeyStorePath(keystore);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
connector.setAllowRenegotiate(true);
server.setConnectors(new Connector[]{ connector });
server.setHandler(new GenericServerHandler());

View File

@ -1,7 +1,5 @@
package org.eclipse.jetty.client.helperClasses;
import java.io.FileInputStream;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
@ -16,9 +14,9 @@ public class AsyncSslServerAndClientCreator extends AbstractSslServerAndClientCr
httpClient.setMaxConnectionsPerAddress(2);
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
httpClient.setKeyStoreInputStream(new FileInputStream(keystore));
httpClient.setKeyStorePassword("storepwd");
httpClient.setKeyManagerPassword("keypwd");
httpClient.getSslContextFactory().setKeyStorePath(keystore);
httpClient.getSslContextFactory().setKeyStorePassword("storepwd");
httpClient.getSslContextFactory().setKeyManagerPassword("keypwd");
httpClient.start();
return httpClient;
}

View File

@ -8,6 +8,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpHeaders;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.IO;
@ -70,6 +71,12 @@ public class GenericServerHandler extends AbstractHandler
{
LOG.debug(e);
}
catch (EofException e)
{
LOG.info(e.toString());
LOG.debug(e);
throw e;
}
catch (IOException e)
{
LOG.warn(e);

View File

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

View File

@ -1,6 +1,7 @@
package org.eclipse.jetty.continuation;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;

View File

@ -233,8 +233,6 @@ public class Jetty6Continuation implements ContinuationFilter.FilteredContinuati
Throwable th=_retry;
_retry=null;
if (th instanceof ThreadDeath)
throw (ThreadDeath)th;
if (th instanceof Error)
throw (Error)th;
if (th instanceof RuntimeException)

View File

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

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.5.5-SNAPSHOT</version>
<version>7.6.0-SNAPSHOT</version>
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>
@ -20,8 +20,7 @@
<orbit-javax-servlet-jsp-version>2.1.0.v201004190952</orbit-javax-servlet-jsp-version>
<orbit-javax-servlet-jsp-jstl-version>1.2.0.v201004190952</orbit-javax-servlet-jsp-jstl-version>
<orbit-com-sun-el-version>1.0.0.v201004190952</orbit-com-sun-el-version>
<!-- orbit-org-apache-jasper-version>2.1.0.v201007080150</orbit-org-apache-jasper-version -->
<central-jsp-version>2.1.3-b10</central-jsp-version>
<orbit-org-apache-jasper-version>2.1.0.v201110031002</orbit-org-apache-jasper-version>
<orbit-org-apache-taglibs-standard-version>1.2.0.v201004190952</orbit-org-apache-taglibs-standard-version>
<orbit-org-objectweb-asm-version>3.1.0.v200803061910</orbit-org-objectweb-asm-version>
<orbit-javax-transaction-version>1.1.1.v201004190952</orbit-javax-transaction-version>
@ -77,7 +76,7 @@
<url url="${jetty-orbit-url}/javax.servlet.jsp_${orbit-javax-servlet-jsp-version}.jar" />
<url url="${jetty-orbit-url}/javax.servlet.jsp.jstl_${orbit-javax-servlet-jsp-jstl-version}.jar" />
<url url="${jetty-orbit-url}/com.sun.el_${orbit-com-sun-el-version}.jar" />
<!-- url url="${jetty-orbit-url}/org.apache.jasper.glassfish_${orbit-org-apache-jasper-version}.jar" / -->
<url url="${jetty-orbit-url}/org.apache.jasper.glassfish_${orbit-org-apache-jasper-version}.jar" />
<url url="${jetty-orbit-url}/org.apache.taglibs.standard.glassfish_${orbit-org-apache-taglibs-standard-version}.jar" />
<url url="${jetty-orbit-url}/org.objectweb.asm_${orbit-org-objectweb-asm-version}.jar" />
<url url="${jetty-orbit-url}/javax.transaction_${orbit-javax-transaction-version}.jar" />
@ -207,24 +206,11 @@
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty</includeGroupIds>
<excludeArtifactIds>jetty-start,jetty-monitor,jetty-jsp-2.1</excludeArtifactIds>
<excludeArtifactIds>jetty-start,jetty-monitor</excludeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-lib-jsp-deps</id>
<phase>generate-resources</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeGroupIds>org.eclipse.jetty,org.glassfish.web</includeGroupIds>
<includeArtifactIds>jetty-jsp-2.1,jsp-impl</includeArtifactIds>
<includeTypes>jar</includeTypes>
<outputDirectory>${assembly-directory}/lib/jsp</outputDirectory>
</configuration>
</execution>
<execution>
<id>copy-lib-monitor-deps</id>
<phase>generate-resources</phase>
@ -388,16 +374,6 @@
<artifactId>jetty-overlay-deployer</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-jsp-2.1</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>org.glassfish.web</groupId>
<artifactId>jsp-impl</artifactId>
<version>${central-jsp-version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-all</artifactId>

View File

@ -18,6 +18,7 @@
# Below are some recommended options for Sun's JRE
#-----------------------------------------------------------
# --exec
# -Dorg.apache.jasper.compiler.disablejsr199=true
# -Dcom.sun.management.jmxremote
# -Dorg.eclipse.jetty.util.log.IGNORED=true
# -Dorg.eclipse.jetty.util.log.stderr.DEBUG=true

View File

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

View File

@ -17,7 +17,6 @@ import com.sun.net.httpserver.Authenticator.Result;
import com.sun.net.httpserver.HttpContext;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpPrincipal;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.ContextHandler;
@ -80,8 +79,7 @@ public class HttpSpiContextHandler extends ContextHandler
}
finally
{
Request base_request = (req instanceof Request) ? (Request)req:HttpConnection.getCurrentConnection().getRequest();
base_request.setHandled(true);
baseRequest.setHandled(true);
}
}

View File

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

View File

@ -100,7 +100,7 @@ public abstract class AbstractGenerator implements Generator
}
/* ------------------------------------------------------------------------------- */
public void reset(boolean returnBuffers)
public void reset()
{
_state = STATE_HEADER;
_status = 0;
@ -114,20 +114,6 @@ public abstract class AbstractGenerator implements Generator
_contentLength = HttpTokens.UNKNOWN_CONTENT;
_date = null;
// always return the body buffer
if (_buffer!=null)
_buffers.returnBuffer(_buffer);
_buffer=null;
if (returnBuffers)
{
if (_header!=null)
_buffers.returnBuffer(_header);
_header=null;
}
else if (_header != null)
_header.clear();
_content = null;
_method=null;
}
@ -436,7 +422,7 @@ public abstract class AbstractGenerator implements Generator
}
/* ------------------------------------------------------------ */
public abstract long flushBuffer() throws IOException;
public abstract int flushBuffer() throws IOException;
/* ------------------------------------------------------------ */
@ -457,15 +443,6 @@ public abstract class AbstractGenerator implements Generator
now=System.currentTimeMillis();
}
}
// make sure buffered data is also flushed
while (now<end && _endp.isBufferingOutput() && _endp.isOpen() && !_endp.isOutputShutdown())
{
if (!_endp.isBlocking())
_endp.blockWritable(end-now);
_endp.flush();
now=System.currentTimeMillis();
}
}
/* ------------------------------------------------------------ */

View File

@ -50,7 +50,7 @@ public interface Generator
void completeHeader(HttpFields responseFields, boolean last) throws IOException;
long flushBuffer() throws IOException;
int flushBuffer() throws IOException;
int getContentBufferSize();
@ -70,7 +70,7 @@ public interface Generator
boolean isPersistent();
void reset(boolean returnBuffers);
void reset();
void resetBuffer();

View File

@ -24,7 +24,7 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle;
*/
public class HttpBuffers extends AbstractLifeCycle
{
private int _requestBufferSize=12*1024;
private int _requestBufferSize=16*1024;
private int _requestHeaderSize=6*1024;
private int _responseBufferSize=32*1024;
private int _responseHeaderSize=6*1024;

View File

@ -38,7 +38,6 @@ import org.eclipse.jetty.io.BufferCache.CachedBuffer;
import org.eclipse.jetty.io.BufferDateCache;
import org.eclipse.jetty.io.BufferUtil;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.io.View;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.QuotedStringTokenizer;
import org.eclipse.jetty.util.StringMap;

View File

@ -125,9 +125,26 @@ public class HttpGenerator extends AbstractGenerator
/* ------------------------------------------------------------------------------- */
@Override
public void reset(boolean returnBuffers)
public void reset()
{
super.reset(returnBuffers);
if (_persistent!=null && !_persistent && _endp!=null && !_endp.isOutputShutdown())
{
try
{
_endp.shutdownOutput();
}
catch(IOException e)
{
LOG.ignore(e);
}
}
super.reset();
if (_buffer!=null)
_buffer.clear();
if (_header!=null)
_header.clear();
if (_content!=null)
_content=null;
_bypass = false;
_needCRLF = false;
_needEOC = false;
@ -137,8 +154,6 @@ public class HttpGenerator extends AbstractGenerator
_noContent=false;
}
/* ------------------------------------------------------------ */
/**
* Add content.
@ -157,8 +172,7 @@ public class HttpGenerator extends AbstractGenerator
if (_last || _state==STATE_END)
{
if (LOG.isDebugEnabled())
LOG.debug("Ignoring extra content {}",content.toDetailString());
LOG.warn("Ignoring extra content {}",content);
content.clear();
return;
}
@ -167,7 +181,7 @@ public class HttpGenerator extends AbstractGenerator
// Handle any unfinished business?
if (_content!=null && _content.length()>0 || _bufferChunked)
{
if (!_endp.isOpen())
if (_endp.isOutputShutdown())
throw new EofException();
flushBuffer();
if (_content != null && _content.length()>0)
@ -243,8 +257,7 @@ public class HttpGenerator extends AbstractGenerator
if (_last || _state==STATE_END)
{
if (LOG.isDebugEnabled())
LOG.debug("Ignoring extra content {}",Byte.valueOf(b));
LOG.warn("Ignoring extra content {}",Byte.valueOf(b));
return false;
}
@ -401,7 +414,7 @@ public class HttpGenerator extends AbstractGenerator
_contentLength = HttpTokens.NO_CONTENT;
_header.put(_method);
_header.put((byte)' ');
_header.put(_uri.getBytes("utf-8")); // TODO WRONG!
_header.put(_uri.getBytes("UTF-8")); // TODO check
_header.put(HttpTokens.CRLF);
_state = STATE_FLUSHING;
_noContent=true;
@ -411,7 +424,7 @@ public class HttpGenerator extends AbstractGenerator
{
_header.put(_method);
_header.put((byte)' ');
_header.put(_uri.getBytes("utf-8")); // TODO WRONG!
_header.put(_uri.getBytes("UTF-8")); // TODO check
_header.put((byte)' ');
_header.put(_version==HttpVersions.HTTP_1_0_ORDINAL?HttpVersions.HTTP_1_0_BUFFER:HttpVersions.HTTP_1_1_BUFFER);
_header.put(HttpTokens.CRLF);
@ -420,7 +433,6 @@ public class HttpGenerator extends AbstractGenerator
else
{
// Responses
if (_version == HttpVersions.HTTP_0_9_ORDINAL)
{
_persistent = false;
@ -679,7 +691,7 @@ public class HttpGenerator extends AbstractGenerator
{
// we have seen all the _content there is
_contentLength = _contentWritten;
if (content_length == null && (isResponse() || _contentLength>0 || content_type ))
if (content_length == null && (isResponse() || _contentLength>0 || content_type ) && !_noContent)
{
// known length but not actually set.
_header.put(HttpHeaders.CONTENT_LENGTH_BUFFER);
@ -778,7 +790,6 @@ public class HttpGenerator extends AbstractGenerator
// end the header.
_header.put(HttpTokens.CRLF);
_state = STATE_CONTENT;
}
@ -788,8 +799,6 @@ public class HttpGenerator extends AbstractGenerator
}
}
/* ------------------------------------------------------------ */
/**
* Complete the message.
@ -816,10 +825,11 @@ public class HttpGenerator extends AbstractGenerator
/* ------------------------------------------------------------ */
@Override
public long flushBuffer() throws IOException
public int flushBuffer() throws IOException
{
try
{
if (_state == STATE_HEADER)
throw new IllegalStateException("State==HEADER");
@ -839,7 +849,12 @@ public class HttpGenerator extends AbstractGenerator
int total= 0;
int len = -1;
int to_flush = ((_header != null && _header.length() > 0)?4:0) | ((_buffer != null && _buffer.length() > 0)?2:0) | ((_bypass && _content != null && _content.length() > 0)?1:0);
int to_flush = flushMask();
int last_flush;
do
{
last_flush=to_flush;
switch (to_flush)
{
case 7:
@ -864,6 +879,7 @@ public class HttpGenerator extends AbstractGenerator
break;
case 0:
{
len=0;
// Nothing more we can write now.
if (_header != null)
_header.clear();
@ -895,24 +911,26 @@ public class HttpGenerator extends AbstractGenerator
if (!_needCRLF && !_needEOC && (_content==null || _content.length()==0))
{
if (_state == STATE_FLUSHING)
{
_state = STATE_END;
}
if (_state==STATE_END && _persistent != null && !_persistent && _status!=100 && _method==null)
{
_endp.shutdownOutput();
}
}
else
// Try to prepare more to write.
prepareBuffers();
}
}
if (len > 0)
total+=len;
to_flush = flushMask();
}
// loop while progress is being made (OR we have prepared some buffers that might make progress)
while (len>0 || (to_flush!=0 && last_flush==0));
return total;
}
catch (IOException e)
@ -922,6 +940,14 @@ public class HttpGenerator extends AbstractGenerator
}
}
/* ------------------------------------------------------------ */
private int flushMask()
{
return ((_header != null && _header.length() > 0)?4:0)
| ((_buffer != null && _buffer.length() > 0)?2:0)
| ((_bypass && _content != null && _content.length() > 0)?1:0);
}
/* ------------------------------------------------------------ */
private void prepareBuffers()
{
@ -940,12 +966,15 @@ public class HttpGenerator extends AbstractGenerator
// Chunk buffer if need be
if (_contentLength == HttpTokens.CHUNKED_CONTENT)
{
if ((_buffer==null||_buffer.length()==0) && _content!=null)
if (_bypass && (_buffer==null||_buffer.length()==0) && _content!=null)
{
// this is a bypass write
int size = _content.length();
_bufferChunked = true;
if (_header == null)
_header = _buffers.getHeader();
// if we need CRLF add this to header
if (_needCRLF)
{
@ -986,7 +1015,10 @@ public class HttpGenerator extends AbstractGenerator
}
else
{
// No space so lets use the header buffer.
// No space so lets use a header buffer.
if (_header == null)
_header = _buffers.getHeader();
if (_needCRLF)
{
if (_header.length() > 0) throw new IllegalStateException("EOC");
@ -1069,9 +1101,11 @@ public class HttpGenerator extends AbstractGenerator
@Override
public String toString()
{
return "HttpGenerator s="+_state+
" h="+(_header==null?"null":_header.length())+
" b="+(_buffer==null?"null":_buffer.length())+
" c="+(_content==null?"null":_content.length());
return String.format("%s{s=%d,h=%d,b=%d,c=%d}",
getClass().getSimpleName(),
_state,
_header == null ? -1 : _header.length(),
_buffer == null ? -1 : _buffer.length(),
_content == null ? -1 : _content.length());
}
}

View File

@ -13,14 +13,9 @@
package org.eclipse.jetty.http;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.io.BufferCache;
import org.eclipse.jetty.io.ByteArrayBuffer;
import org.eclipse.jetty.util.log.Log;
/**
* Cached HTTP Header values.

View File

@ -13,7 +13,6 @@
package org.eclipse.jetty.http;
import java.io.EOFException;
import java.io.IOException;
import org.eclipse.jetty.io.Buffer;
@ -55,6 +54,7 @@ public class HttpParser implements Parser
public static final int STATE_CHUNK_SIZE=4;
public static final int STATE_CHUNK_PARAMS=5;
public static final int STATE_CHUNK=6;
public static final int STATE_SEEKING_EOF=7;
private final EventHandler _handler;
private final Buffers _buffers; // source of buffers
@ -68,6 +68,7 @@ public class HttpParser implements Parser
private String _multiLineValue;
private int _responseStatus; // If >0 then we are parsing a response
private boolean _forceContentBuffer;
private boolean _persistent;
/* ------------------------------------------------------------------------------- */
protected final View _contentView=new View(); // View of the content in the buffer for {@link Input}
@ -186,6 +187,20 @@ public class HttpParser implements Parser
return _state == state;
}
/* ------------------------------------------------------------------------------- */
public boolean isPersistent()
{
return _persistent;
}
/* ------------------------------------------------------------------------------- */
public void setPersistent(boolean persistent)
{
_persistent = persistent;
if (_state==STATE_END)
_state=STATE_SEEKING_EOF;
}
/* ------------------------------------------------------------------------------- */
/**
* Parse until {@link #STATE_END END} state.
@ -213,19 +228,16 @@ public class HttpParser implements Parser
* @see #parse
* @see #parseNext
*/
public int parseAvailable() throws IOException
public boolean parseAvailable() throws IOException
{
int progress = parseNext();
int total=progress>0?1:0;
boolean progress=parseNext()>0;
// continue parsing
while (!isComplete() && _buffer!=null && _buffer.length()>0)
{
progress = parseNext();
if (progress>0)
total++;
progress |= parseNext()>0;
}
return total;
return progress;
}
@ -235,6 +247,8 @@ public class HttpParser implements Parser
* @return an indication of progress <0 EOF, 0 no progress, >0 progress.
*/
public int parseNext() throws IOException
{
try
{
int progress=0;
@ -259,6 +273,7 @@ public class HttpParser implements Parser
{
_state=STATE_END;
_handler.messageComplete(_contentPosition);
returnBuffers();
return 1;
}
@ -267,11 +282,12 @@ public class HttpParser implements Parser
// Fill buffer if we can
if (length == 0)
{
long filled=-1;
int filled=-1;
IOException ex=null;
try
{
filled=fill();
LOG.debug("filled {}/{}",filled,_buffer.length());
}
catch(IOException e)
{
@ -279,27 +295,42 @@ public class HttpParser implements Parser
ex=e;
}
if (filled < 0 || _endp.isInputShutdown())
if (filled > 0 )
progress++;
else if (filled < 0 )
{
if (_headResponse && _state>STATE_END)
_persistent=false;
// do we have content to deliver?
if (_state>STATE_END)
{
_state=STATE_END;
_handler.messageComplete(_contentPosition);
return 1;
}
if ( _state == STATE_EOF_CONTENT)
if (_buffer.length()>0 && !_headResponse)
{
if (_buffer.length()>0)
{
// TODO should we do this here or fall down to main loop?
Buffer chunk=_buffer.get(_buffer.length());
_contentPosition += chunk.length();
_contentView.update(chunk);
_handler.content(chunk); // May recurse here
}
}
// was this unexpected?
switch(_state)
{
case STATE_END:
case STATE_SEEKING_EOF:
_state=STATE_END;
break;
case STATE_EOF_CONTENT:
_state=STATE_END;
_handler.messageComplete(_contentPosition);
return 1;
break;
default:
_state=STATE_END;
if (!_headResponse)
_handler.earlyEOF();
_handler.messageComplete(_contentPosition);
}
if (ex!=null)
@ -308,13 +339,14 @@ public class HttpParser implements Parser
if (!isComplete() && !isIdle())
throw new EofException();
returnBuffers();
return -1;
}
length=_buffer.length();
}
// EventHandler header
// Handle header states
byte ch;
byte[] array=_buffer.array();
int last=_state;
@ -417,9 +449,11 @@ public class HttpParser implements Parser
{
// HTTP/0.9
_handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _buffer.sliceFromMark(), null);
_state=STATE_END;
_persistent=false;
_state=STATE_SEEKING_EOF;
_handler.headerComplete();
_handler.messageComplete(_contentPosition);
returnBuffers();
return 1;
}
break;
@ -445,9 +479,11 @@ public class HttpParser implements Parser
{
// HTTP/0.9
_handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _tok1, null);
_state=STATE_END;
_persistent=false;
_state=STATE_SEEKING_EOF;
_handler.headerComplete();
_handler.messageComplete(_contentPosition);
returnBuffers();
return 1;
}
}
@ -456,11 +492,13 @@ public class HttpParser implements Parser
case STATE_FIELD2:
if (ch == HttpTokens.CARRIAGE_RETURN || ch == HttpTokens.LINE_FEED)
{
Buffer version;
if (_responseStatus>0)
_handler.startResponse(HttpVersions.CACHE.lookup(_tok0), _responseStatus,_buffer.sliceFromMark());
_handler.startResponse(version=HttpVersions.CACHE.lookup(_tok0), _responseStatus,_buffer.sliceFromMark());
else
_handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _tok1, HttpVersions.CACHE.lookup(_buffer.sliceFromMark()));
_handler.startRequest(HttpMethods.CACHE.lookup(_tok0), _tok1, version=HttpVersions.CACHE.lookup(_buffer.sliceFromMark()));
_eol=ch;
_persistent=HttpVersions.CACHE.getOrdinal(version)>=HttpVersions.HTTP_1_1_ORDINAL;
_state=STATE_HEADER;
_tok0.setPutIndex(_tok0.getIndex());
_tok1.setPutIndex(_tok1.getIndex());
@ -487,7 +525,6 @@ public class HttpParser implements Parser
// handler last header if any
if (_cached!=null || _tok0.length() > 0 || _tok1.length() > 0 || _multiLineValue != null)
{
Buffer header=_cached!=null?_cached:HttpHeaders.CACHE.lookup(_tok0);
_cached=null;
Buffer value=_multiLineValue == null ? _tok1 : new ByteArrayBuffer(_multiLineValue);
@ -531,6 +568,36 @@ public class HttpParser implements Parser
throw new HttpException(400,null);
}
break;
case HttpHeaders.CONNECTION_ORDINAL:
switch(HttpHeaderValues.CACHE.getOrdinal(value))
{
case HttpHeaderValues.CLOSE_ORDINAL:
_persistent=false;
break;
case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
_persistent=true;
break;
case -1: // No match, may be multi valued
{
for (String v : value.toString().split(","))
{
switch(HttpHeaderValues.CACHE.getOrdinal(v.trim()))
{
case HttpHeaderValues.CLOSE_ORDINAL:
_persistent=false;
break;
case HttpHeaderValues.KEEP_ALIVE_ORDINAL:
_persistent=true;
break;
}
}
break;
}
}
}
}
@ -577,11 +644,11 @@ public class HttpParser implements Parser
break;
case HttpTokens.NO_CONTENT:
_state=STATE_END;
returnBuffers();
_handler.headerComplete();
_state=_persistent||(_responseStatus>=100&&_responseStatus<200)?STATE_END:STATE_SEEKING_EOF;
_handler.messageComplete(_contentPosition);
break;
returnBuffers();
return 1;
default:
_state=STATE_CONTENT;
@ -743,10 +810,11 @@ public class HttpParser implements Parser
// Handle HEAD response
if (_responseStatus>0 && _headResponse)
{
_state=STATE_END;
_state=_persistent||(_responseStatus>=100&&_responseStatus<200)?STATE_END:STATE_SEEKING_EOF;
_handler.messageComplete(_contentLength);
}
// ==========================
// Handle _content
@ -783,8 +851,9 @@ public class HttpParser implements Parser
long remaining=_contentLength - _contentPosition;
if (remaining == 0)
{
_state=STATE_END;
_state=_persistent?STATE_END:STATE_SEEKING_EOF;
_handler.messageComplete(_contentPosition);
returnBuffers();
return 1;
}
@ -802,8 +871,9 @@ public class HttpParser implements Parser
if(_contentPosition == _contentLength)
{
_state=STATE_END;
_state=_persistent?STATE_END:STATE_SEEKING_EOF;
_handler.messageComplete(_contentPosition);
returnBuffers();
}
// TODO adjust the _buffer to keep unconsumed content
return 1;
@ -836,8 +906,9 @@ public class HttpParser implements Parser
{
if (_eol==HttpTokens.CARRIAGE_RETURN && _buffer.hasContent() && _buffer.peek()==HttpTokens.LINE_FEED)
_eol=_buffer.get();
_state=STATE_END;
_state=_persistent?STATE_END:STATE_SEEKING_EOF;
_handler.messageComplete(_contentPosition);
returnBuffers();
return 1;
}
else
@ -866,8 +937,9 @@ public class HttpParser implements Parser
{
if (_eol==HttpTokens.CARRIAGE_RETURN && _buffer.hasContent() && _buffer.peek()==HttpTokens.LINE_FEED)
_eol=_buffer.get();
_state=STATE_END;
_state=_persistent?STATE_END:STATE_SEEKING_EOF;
_handler.messageComplete(_contentPosition);
returnBuffers();
return 1;
}
else
@ -894,6 +966,13 @@ public class HttpParser implements Parser
// TODO adjust the _buffer to keep unconsumed content
return 1;
}
case STATE_SEEKING_EOF:
{
// Skip all data
_buffer.clear();
break;
}
}
length=_buffer.length();
@ -901,12 +980,19 @@ public class HttpParser implements Parser
return progress;
}
catch(HttpException e)
{
_persistent=false;
_state=STATE_SEEKING_EOF;
throw e;
}
}
/* ------------------------------------------------------------------------------- */
/** fill the buffers from the endpoint
*
*/
public long fill() throws IOException
protected int fill() throws IOException
{
// Do we have a buffer?
if (_buffer==null)
@ -942,11 +1028,15 @@ public class HttpParser implements Parser
// Are we full?
if (_buffer.space() == 0)
{
LOG.warn("Full {}",_buffer.toDetailString());
throw new HttpException(HttpStatus.REQUEST_ENTITY_TOO_LARGE_413, "FULL "+(_buffer==_body?"body":"head"));
}
try
{
return _endp.fill(_buffer);
int filled = _endp.fill(_buffer);
return filled;
}
catch(IOException e)
{
@ -958,45 +1048,12 @@ public class HttpParser implements Parser
return -1;
}
/* ------------------------------------------------------------------------------- */
/** Skip any CRLFs in buffers
*
*/
public void skipCRLF()
{
while (_header!=null && _header.length()>0)
{
byte ch = _header.peek();
if (ch==HttpTokens.CARRIAGE_RETURN || ch==HttpTokens.LINE_FEED)
{
_eol=ch;
_header.skip(1);
}
else
break;
}
while (_body!=null && _body.length()>0)
{
byte ch = _body.peek();
if (ch==HttpTokens.CARRIAGE_RETURN || ch==HttpTokens.LINE_FEED)
{
_eol=ch;
_body.skip(1);
}
else
break;
}
}
/* ------------------------------------------------------------------------------- */
public void reset()
{
// reset state
_contentView.setGetIndex(_contentView.putIndex());
_state=STATE_START;
_state=_persistent?STATE_START:(_endp.isInputShutdown()?STATE_END:STATE_SEEKING_EOF);
_contentLength=HttpTokens.UNKNOWN_CONTENT;
_contentPosition=0;
_length=0;
@ -1036,6 +1093,7 @@ public class HttpParser implements Parser
_body.setMarkIndex(-1);
_buffer=_header;
returnBuffers();
}
@ -1077,7 +1135,11 @@ public class HttpParser implements Parser
@Override
public String toString()
{
return "state=" + _state + " length=" + _length + " len=" + _contentLength;
return String.format("%s{s=%d,l=%d,c=%d}",
getClass().getSimpleName(),
_state,
_length,
_contentLength);
}
/* ------------------------------------------------------------ */
@ -1110,7 +1172,8 @@ public class HttpParser implements Parser
{
if (_contentView.length()>0)
return _contentView;
if (getState() <= HttpParser.STATE_END)
if (getState() <= STATE_END || isState(STATE_SEEKING_EOF))
return null;
try
@ -1118,11 +1181,11 @@ public class HttpParser implements Parser
parseNext();
// parse until some progress is made (or IOException thrown for timeout)
while(_contentView.length() == 0 && !isState(HttpParser.STATE_END) && _endp!=null && _endp.isOpen())
while(_contentView.length() == 0 && !(isState(HttpParser.STATE_END)||isState(HttpParser.STATE_SEEKING_EOF)) && _endp!=null && _endp.isOpen())
{
if (!_endp.isBlocking())
{
if (_endp.isBufferingInput() && parseNext()>0)
if (parseNext()>0)
continue;
if (!_endp.blockReadable(maxIdleTime))
@ -1137,6 +1200,7 @@ public class HttpParser implements Parser
}
catch(IOException e)
{
// TODO is this needed?
_endp.close();
throw e;
}
@ -1198,6 +1262,9 @@ public class HttpParser implements Parser
*/
public abstract void startResponse(Buffer version, int status, Buffer reason)
throws IOException;
public void earlyEOF()
{}
}

View File

@ -26,13 +26,17 @@ public interface Parser
boolean isComplete();
/**
* @return An indication of progress, typically the number of bytes filled plus the events parsed: -1 means EOF read, 0 no progress, >0 progress
* @return True if progress made
* @throws IOException
*/
int parseAvailable() throws IOException;
boolean parseAvailable() throws IOException;
boolean isMoreInBuffer() throws IOException;
boolean isIdle();
boolean isPersistent();
void setPersistent(boolean persistent);
}

View File

@ -22,7 +22,6 @@ import java.io.UnsupportedEncodingException;
import java.util.Set;
import javax.servlet.ServletOutputStream;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
@ -121,7 +120,7 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
public void setStatus(int sc, String sm)
{
super.setStatus(sc,sm);
if (sc<200||sc>=300)
if (sc<200 || sc==204 || sc==205 || sc>=300)
noGzip();
}
@ -132,7 +131,7 @@ public class GzipResponseWrapper extends HttpServletResponseWrapper
public void setStatus(int sc)
{
super.setStatus(sc);
if (sc<200||sc>=300)
if (sc<200 || sc==204 || sc==205 ||sc>=300)
noGzip();
}

View File

@ -14,10 +14,9 @@
package org.eclipse.jetty.http;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse;
import java.util.Enumeration;
import java.util.HashSet;

View File

@ -138,7 +138,7 @@ public class HttpGeneratorClientTest
String t="v="+v+",r="+r+",chunks="+chunks+",c="+c+",tr="+tr[r];
// System.err.println(t);
hb.reset(true);
hb.reset();
endp.reset();
fields.clear();
@ -193,7 +193,7 @@ public class HttpGeneratorClientTest
}
private static final String[] headers= { "Content-Type","Content-Length","Connection","Transfer-Encoding","Other"};
private class TR
private static class TR
{
private String[] values=new String[headers.length];
private String body;

View File

@ -86,7 +86,7 @@ public class HttpGeneratorTest
String t="v="+v+",r="+r+",chunks="+chunks+",connect="+c+",tr="+tr[r];
// System.err.println(t);
hb.reset(true);
hb.reset();
endp.reset();
fields.clear();
@ -138,7 +138,7 @@ public class HttpGeneratorTest
}
private static final String[] headers= { "Content-Type","Content-Length","Connection","Transfer-Encoding","Other"};
private class TR
private static class TR
{
private int _code;
private String _body;

View File

@ -210,6 +210,7 @@ public class HttpParserTest
StringEndPoint io=new StringEndPoint();
io.setInput(
"GET /mp HTTP/1.0\015\012"
+ "Connection: Keep-Alive\015\012"
+ "Header1: value1\015\012"
+ "Transfer-Encoding: chunked\015\012"
+ "\015\012"
@ -219,10 +220,12 @@ public class HttpParserTest
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ\015\012"
+ "0\015\012"
+ "POST /foo HTTP/1.0\015\012"
+ "Connection: Keep-Alive\015\012"
+ "Header2: value2\015\012"
+ "Content-Length: 0\015\012"
+ "\015\012"
+ "PUT /doodle HTTP/1.0\015\012"
+ "Connection: close\015\012"
+ "Header3: value3\015\012"
+ "Content-Length: 10\015\012"
+ "\015\012"
@ -238,27 +241,27 @@ public class HttpParserTest
assertEquals("GET", f0);
assertEquals("/mp", f1);
assertEquals("HTTP/1.0", f2);
assertEquals(1, h);
assertEquals("Header1", hdr[0]);
assertEquals("value1", val[0]);
assertEquals(2, h);
assertEquals("Header1", hdr[1]);
assertEquals("value1", val[1]);
assertEquals("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content);
parser.parse();
assertEquals("POST", f0);
assertEquals("/foo", f1);
assertEquals("HTTP/1.0", f2);
assertEquals(1, h);
assertEquals("Header2", hdr[0]);
assertEquals("value2", val[0]);
assertEquals(2, h);
assertEquals("Header2", hdr[1]);
assertEquals("value2", val[1]);
assertEquals(null, _content);
parser.parse();
assertEquals("PUT", f0);
assertEquals("/doodle", f1);
assertEquals("HTTP/1.0", f2);
assertEquals(1, h);
assertEquals("Header3", hdr[0]);
assertEquals("value3", val[0]);
assertEquals(2, h);
assertEquals("Header3", hdr[1]);
assertEquals("value3", val[1]);
assertEquals("0123456789", _content);
}
@ -266,7 +269,8 @@ public class HttpParserTest
public void testStreamParse() throws Exception
{
StringEndPoint io=new StringEndPoint();
String http="GET / HTTP/1.0\015\012"
String http="GET / HTTP/1.1\015\012"
+ "Host: test\015\012"
+ "Header1: value1\015\012"
+ "Transfer-Encoding: chunked\015\012"
+ "\015\012"
@ -275,11 +279,14 @@ public class HttpParserTest
+ "1a\015\012"
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ\015\012"
+ "0\015\012"
+ "POST /foo HTTP/1.0\015\012"
+ "POST /foo HTTP/1.1\015\012"
+ "Host: test\015\012"
+ "Header2: value2\015\012"
+ "Content-Length: 0\015\012"
+ "\015\012"
+ "PUT /doodle HTTP/1.0\015\012"
+ "PUT /doodle HTTP/1.1\015\012"
+ "Host: test\015\012"
+ "Connection: close\015\012"
+ "Header3: value3\015\012"
+ "Content-Length: 10\015\012"
+ "\015\012"
@ -296,15 +303,17 @@ public class HttpParserTest
http.length() - 2,
http.length() / 2,
http.length() / 3,
64,
128,
32
};
for (int t= 0; t < tests.length; t++)
{
String tst="t"+tests[t];
String tst="t"+t+"="+tests[t];
try
{
f0=f1=f2=null;
h=0;
ByteArrayBuffer buffer= new ByteArrayBuffer(tests[t]);
ByteArrayBuffer content=new ByteArrayBuffer(8192);
SimpleBuffers buffers=new SimpleBuffers(buffer,content);
@ -314,31 +323,32 @@ public class HttpParserTest
io.setInput(http);
// System.err.println(tst);
parser.parse();
assertEquals(tst,"GET", f0);
assertEquals(tst,"/", f1);
assertEquals(tst,"HTTP/1.0", f2);
assertEquals(tst,1, h);
assertEquals(tst,"Header1", hdr[0]);
assertEquals(tst,"value1", val[0]);
assertEquals(tst,"HTTP/1.1", f2);
assertEquals(tst,2, h);
assertEquals(tst,"Header1", hdr[1]);
assertEquals(tst,"value1", val[1]);
assertEquals(tst,"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ", _content);
parser.parse();
assertEquals(tst,"POST", f0);
assertEquals(tst,"/foo", f1);
assertEquals(tst,"HTTP/1.0", f2);
assertEquals(tst,1, h);
assertEquals(tst,"Header2", hdr[0]);
assertEquals(tst,"value2", val[0]);
assertEquals(tst,"HTTP/1.1", f2);
assertEquals(tst,2, h);
assertEquals(tst,"Header2", hdr[1]);
assertEquals(tst,"value2", val[1]);
assertEquals(tst,null, _content);
parser.parse();
assertEquals(tst,"PUT", f0);
assertEquals(tst,"/doodle", f1);
assertEquals(tst,"HTTP/1.0", f2);
assertEquals(tst,1, h);
assertEquals(tst,"Header3", hdr[0]);
assertEquals(tst,"value3", val[0]);
assertEquals(tst,"HTTP/1.1", f2);
assertEquals(tst,3, h);
assertEquals(tst,"Header3", hdr[2]);
assertEquals(tst,"value3", val[2]);
assertEquals(tst,"0123456789", _content);
}
catch(Exception e)
@ -401,7 +411,7 @@ public class HttpParserTest
StringEndPoint io=new StringEndPoint();
io.setInput(
"HTTP/1.1 204 No-Content\015\012"
+ "Connection: close\015\012"
+ "Header: value\015\012"
+ "\015\012"
+ "HTTP/1.1 200 Correct\015\012"
+ "Content-Length: 10\015\012"

View File

@ -1,75 +0,0 @@
package org.eclipse.jetty.http;
import static junit.framework.Assert.assertTrue;
import java.io.FileInputStream;
import java.security.KeyStore;
import org.eclipse.jetty.http.ssl.SslContextFactory;
import org.junit.Test;
public class SslContextFactoryTest
{
@Test
public void testNoTsFileKs() throws Exception
{
String keystorePath = System.getProperty("basedir",".") + "/src/test/resources/keystore";
SslContextFactory cf = new SslContextFactory(keystorePath);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
cf.start();
assertTrue(cf.getSslContext()!=null);
}
@Test
public void testNoTsStreamKs() throws Exception
{
String keystorePath = System.getProperty("basedir",".") + "/src/test/resources/keystore";
SslContextFactory cf = new SslContextFactory();
cf.setKeyStoreInputStream(new FileInputStream(keystorePath));
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
cf.start();
assertTrue(cf.getSslContext()!=null);
}
@Test
public void testNoTsSetKs() throws Exception
{
String keystorePath = System.getProperty("basedir",".") + "/src/test/resources/keystore";
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream(keystorePath),"storepwd".toCharArray());
SslContextFactory cf = new SslContextFactory();
cf.setKeyStore(ks);
cf.setKeyManagerPassword("keypwd");
cf.start();
assertTrue(cf.getSslContext()!=null);
}
@Test
public void testNoTsNoKs() throws Exception
{
SslContextFactory cf = new SslContextFactory();
cf.start();
assertTrue(cf.getSslContext()!=null);
}
@Test
public void testTrustAll() throws Exception
{
SslContextFactory cf = new SslContextFactory();
cf.start();
assertTrue(cf.getSslContext()!=null);
}
}

View File

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

View File

@ -15,13 +15,13 @@ public abstract class AbstractConnection implements Connection
public AbstractConnection(EndPoint endp)
{
_endp=endp;
_endp=(EndPoint)endp;
_timeStamp = System.currentTimeMillis();
}
public AbstractConnection(EndPoint endp,long timestamp)
{
_endp=endp;
_endp=(EndPoint)endp;
_timeStamp = timestamp;
}
@ -35,10 +35,14 @@ public abstract class AbstractConnection implements Connection
return _endp;
}
public void idleExpired()
public void onIdleExpired()
{
try
{
LOG.debug("onIdleExpired {} {}",this,_endp);
if (_endp.isInputShutdown() || _endp.isOutputShutdown())
_endp.close();
else
_endp.shutdownOutput();
}
catch(IOException e)
@ -52,13 +56,18 @@ public abstract class AbstractConnection implements Connection
catch(IOException e2)
{
LOG.ignore(e2);
}
}
}
public String toString()
{
return super.toString()+"@"+_endp.getLocalAddr()+":"+_endp.getLocalPort()+"<->"+_endp.getRemoteAddr()+":"+_endp.getRemotePort();
return String.format("%s@%x//%s:%d<->%s:%d",
getClass().getSimpleName(),
hashCode(),
_endp.getLocalAddr(),
_endp.getLocalPort(),
_endp.getRemoteAddr(),
_endp.getRemotePort());
}
}

View File

@ -13,20 +13,16 @@
package org.eclipse.jetty.io;
public interface AsyncEndPoint extends EndPoint
import org.eclipse.jetty.util.thread.Timeout;
public interface AsyncEndPoint extends ConnectedEndPoint
{
/* ------------------------------------------------------------ */
/**
* Dispatch the endpoint to a thread to attend to it.
*
*/
public void dispatch();
/**
* @return true if this endpoint can accept a dispatch. False if the
* endpoint cannot accept a dispatched (eg is suspended or already dispatched)
*/
public boolean isReadyForDispatch();
public void asyncDispatch();
/* ------------------------------------------------------------ */
/** Schedule a write dispatch.
@ -36,13 +32,39 @@ public interface AsyncEndPoint extends EndPoint
public void scheduleWrite();
/* ------------------------------------------------------------ */
/** Schedule a call to the idle timeout
/** Callback when idle.
* <p>An endpoint is idle if there has been no IO activity for
* {@link #getMaxIdleTime()} and {@link #isCheckForIdle()} is true.
*/
public void scheduleIdle();
public void onIdleExpired();
/* ------------------------------------------------------------ */
/** Cancel a call to the idle timeout
/** Set if the endpoint should be checked for idleness
*/
public void cancelIdle();
public void setCheckForIdle(boolean check);
/* ------------------------------------------------------------ */
/** Get if the endpoint should be checked for idleness
*/
public boolean isCheckForIdle();
/* ------------------------------------------------------------ */
public boolean isWritable();
/* ------------------------------------------------------------ */
/**
* @return True if IO has been successfully performed since the last call to {@link #hasProgressed()}
*/
public boolean hasProgressed();
/* ------------------------------------------------------------ */
/**
*/
public void scheduleTimeout(Timeout.Task task, long timeoutMs);
/* ------------------------------------------------------------ */
/**
*/
public void cancelTimeout(Timeout.Task task);
}

View File

@ -103,6 +103,12 @@ public class BufferCache
return lookup(buffer).toString();
}
public int getOrdinal(String value)
{
CachedBuffer buffer = (CachedBuffer)_stringMap.get(value);
return buffer==null?-1:buffer.getOrdinal();
}
public int getOrdinal(Buffer buffer)
{
if (buffer instanceof CachedBuffer)

View File

@ -46,7 +46,6 @@ public class BufferDateCache extends DateCache
public synchronized Buffer formatBuffer(long date)
{
String d = super.format(date);
//noinspection StringEquality
if (d==_last)
return _buffer;
_last=d;

View File

@ -363,24 +363,6 @@ public class ByteArrayEndPoint implements ConnectedEndPoint
{
}
/* ------------------------------------------------------------ */
public boolean isBufferingInput()
{
return false;
}
/* ------------------------------------------------------------ */
public boolean isBufferingOutput()
{
return false;
}
/* ------------------------------------------------------------ */
public boolean isBufferred()
{
return false;
}
/* ------------------------------------------------------------ */
/**
* @return the growOutput

View File

@ -50,10 +50,10 @@ public interface Connection
/**
* Called when the connection is closed
*/
void closed();
void onClose();
/**
* Called when the connection idle timeout expires
*/
void idleExpired();
void onIdleExpired();
}

View File

@ -122,13 +122,9 @@ public interface EndPoint
*/
public int getRemotePort();
/* ------------------------------------------------------------ */
public boolean isBlocking();
/* ------------------------------------------------------------ */
public boolean isBufferred();
/* ------------------------------------------------------------ */
public boolean blockReadable(long millisecs) throws IOException;
@ -144,18 +140,6 @@ public interface EndPoint
*/
public Object getTransport();
/* ------------------------------------------------------------ */
/**
* @return True if the endpoint has some buffered input data
*/
public boolean isBufferingInput();
/* ------------------------------------------------------------ */
/**
* @return True if the endpoint has some buffered output data
*/
public boolean isBufferingOutput();
/* ------------------------------------------------------------ */
/** Flush any buffered output.
* May fail to write all data if endpoint is non-blocking
@ -163,7 +147,6 @@ public interface EndPoint
*/
public void flush() throws IOException;
/* ------------------------------------------------------------ */
/** Get the max idle time in ms.
* <p>The max idle time is the time the endpoint can be idle before

View File

@ -15,6 +15,13 @@ package org.eclipse.jetty.io;
import java.io.EOFException;
/* ------------------------------------------------------------ */
/** A Jetty specialization of EOFException.
* <p> This is thrown by Jetty to distinguish between EOF received from
* the connection, vs and EOF thrown by some application talking to some other file/socket etc.
* The only difference in handling is that Jetty EOFs are logged less verbosely.
*/
public class EofException extends EOFException
{
public EofException()

View File

@ -17,17 +17,13 @@ import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import javax.net.ssl.SSLSocket;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
*
* To change the template for this generated type comment go to
* Window - Preferences - Java - Code Generation - Code and Comments
*/
public class SocketEndPoint extends StreamEndPoint
{
private static final Logger LOG = Log.getLogger(SocketEndPoint.class);
@ -79,14 +75,34 @@ public class SocketEndPoint extends StreamEndPoint
@Override
public boolean isInputShutdown()
{
return !isOpen() || super.isInputShutdown();
if (_socket instanceof SSLSocket)
return super.isInputShutdown();
return _socket.isClosed() || _socket.isInputShutdown();
}
/* ------------------------------------------------------------ */
@Override
public boolean isOutputShutdown()
{
return !isOpen() || super.isOutputShutdown();
if (_socket instanceof SSLSocket)
return super.isOutputShutdown();
return _socket.isClosed() || _socket.isOutputShutdown();
}
/* ------------------------------------------------------------ */
/*
*/
protected final void shutdownSocketOutput() throws IOException
{
if (!_socket.isClosed())
{
if (!_socket.isOutputShutdown())
_socket.shutdownOutput();
if (_socket.isInputShutdown())
_socket.close();
}
}
/* ------------------------------------------------------------ */
@ -96,15 +112,27 @@ public class SocketEndPoint extends StreamEndPoint
@Override
public void shutdownOutput() throws IOException
{
if (!isOutputShutdown())
{
if (_socket instanceof SSLSocket)
super.shutdownOutput();
if (!(_socket instanceof SSLSocket))
_socket.shutdownOutput();
}
else
shutdownSocketOutput();
}
/* ------------------------------------------------------------ */
/*
*/
public void shutdownSocketInput() throws IOException
{
if (!_socket.isClosed())
{
if (!_socket.isInputShutdown())
_socket.shutdownInput();
if (_socket.isOutputShutdown())
_socket.close();
}
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.io.bio.StreamEndPoint#shutdownOutput()
@ -112,12 +140,10 @@ public class SocketEndPoint extends StreamEndPoint
@Override
public void shutdownInput() throws IOException
{
if (!isInputShutdown())
{
if (_socket instanceof SSLSocket)
super.shutdownInput();
if (!(_socket instanceof SSLSocket))
_socket.shutdownInput();
}
else
shutdownSocketInput();
}
/* ------------------------------------------------------------ */
@ -247,4 +273,9 @@ public class SocketEndPoint extends StreamEndPoint
}
}
@Override
public String toString()
{
return _local + " <--> " + _remote;
}
}

View File

@ -72,10 +72,8 @@ public class StreamEndPoint implements EndPoint
public void shutdownOutput() throws IOException
{
if (_oshut)
return;
_oshut = true;
if (_out!=null)
if (_ishut && _out!=null)
_out.close();
}
@ -86,10 +84,8 @@ public class StreamEndPoint implements EndPoint
public void shutdownInput() throws IOException
{
if (_ishut)
return;
_ishut = true;
if (_in!=null)
if (_oshut&&_in!=null)
_in.close();
}
@ -122,6 +118,8 @@ public class StreamEndPoint implements EndPoint
*/
public int fill(Buffer buffer) throws IOException
{
if (_ishut)
return -1;
if (_in==null)
return 0;
@ -135,15 +133,10 @@ public class StreamEndPoint implements EndPoint
try
{
int read=buffer.readFrom(_in, space);
if (read<0 && isOpen())
{
if (!isInputShutdown())
int filled=buffer.readFrom(_in, space);
if (filled<0)
shutdownInput();
else if (isOutputShutdown())
close();
}
return read;
return filled;
}
catch(SocketTimeoutException e)
{
@ -157,8 +150,10 @@ public class StreamEndPoint implements EndPoint
*/
public int flush(Buffer buffer) throws IOException
{
if (_out==null)
if (_oshut)
return -1;
if (_out==null)
return 0;
int length=buffer.length();
if (length>0)
buffer.writeTo(_out);
@ -310,24 +305,6 @@ public class StreamEndPoint implements EndPoint
_out.flush();
}
/* ------------------------------------------------------------ */
public boolean isBufferingInput()
{
return false;
}
/* ------------------------------------------------------------ */
public boolean isBufferingOutput()
{
return false;
}
/* ------------------------------------------------------------ */
public boolean isBufferred()
{
return false;
}
/* ------------------------------------------------------------ */
public int getMaxIdleTime()
{

View File

@ -53,6 +53,8 @@ public class StringEndPoint extends StreamEndPoint
_in=_bin;
_bout = new ByteArrayOutputStream();
_out=_bout;
_ishut=false;
_oshut=false;
}
catch(Exception e)
{

View File

@ -0,0 +1,23 @@
// ========================================================================
// Copyright (c) 2010 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.io.nio;
import java.io.IOException;
import org.eclipse.jetty.io.Connection;
public interface AsyncConnection extends Connection
{
void onInputShutdown() throws IOException;
}

View File

@ -43,7 +43,9 @@ public class ChannelEndPoint implements EndPoint
protected final Socket _socket;
protected final InetSocketAddress _local;
protected final InetSocketAddress _remote;
protected int _maxIdleTime;
protected volatile int _maxIdleTime;
private volatile boolean _ishut;
private volatile boolean _oshut;
public ChannelEndPoint(ByteChannel channel) throws IOException
{
@ -102,20 +104,76 @@ public class ChannelEndPoint implements EndPoint
return _channel.isOpen();
}
/** Shutdown the channel Input.
* Cannot be overridden. To override, see {@link #shutdownInput()}
* @throws IOException
*/
protected final void shutdownChannelInput() throws IOException
{
LOG.debug("ishut {}", this);
_ishut = true;
if (_channel.isOpen())
{
if (_socket != null)
{
try
{
if (!_socket.isInputShutdown())
{
_socket.shutdownInput();
}
}
catch (SocketException e)
{
LOG.debug(e.toString());
LOG.ignore(e);
}
finally
{
if (_oshut)
{
close();
}
}
}
}
}
/* (non-Javadoc)
* @see org.eclipse.io.EndPoint#close()
*/
public void shutdownInput() throws IOException
{
if (_channel.isOpen() && _channel instanceof SocketChannel)
shutdownChannelInput();
}
protected final void shutdownChannelOutput() throws IOException
{
Socket socket= ((SocketChannel)_channel).socket();
if (!socket.isClosed())
LOG.debug("oshut {}",this);
_oshut = true;
if (_channel.isOpen())
{
if(socket.isOutputShutdown())
socket.close();
else if (!socket.isInputShutdown())
socket.shutdownInput();
if (_socket != null)
{
try
{
if (!_socket.isOutputShutdown())
{
_socket.shutdownOutput();
}
}
catch (SocketException e)
{
LOG.debug(e.toString());
LOG.ignore(e);
}
finally
{
if (_ishut)
{
close();
}
}
}
}
}
@ -125,34 +183,17 @@ public class ChannelEndPoint implements EndPoint
*/
public void shutdownOutput() throws IOException
{
if (_channel.isOpen() && _channel instanceof SocketChannel)
{
Socket socket= ((SocketChannel)_channel).socket();
if (!socket.isClosed())
{
try
{
if (socket.isInputShutdown())
socket.close();
else if (!socket.isOutputShutdown())
socket.shutdownOutput();
}
catch(SocketException e)
{
LOG.ignore(e);
}
}
}
shutdownChannelOutput();
}
public boolean isOutputShutdown()
{
return _channel.isOpen() && _socket!=null && _socket.isOutputShutdown();
return _oshut || !_channel.isOpen() || _socket != null && _socket.isOutputShutdown();
}
public boolean isInputShutdown()
{
return _channel.isOpen() && _socket!=null && _socket.isInputShutdown();
return _ishut || !_channel.isOpen() || _socket != null && _socket.isInputShutdown();
}
/* (non-Javadoc)
@ -160,6 +201,7 @@ public class ChannelEndPoint implements EndPoint
*/
public void close() throws IOException
{
LOG.debug("close {}",this);
_channel.close();
}
@ -168,6 +210,8 @@ public class ChannelEndPoint implements EndPoint
*/
public int fill(Buffer buffer) throws IOException
{
if (_ishut)
return -1;
Buffer buf = buffer.buffer();
int len=0;
if (buf instanceof NIOBuffer)
@ -196,18 +240,20 @@ public class ChannelEndPoint implements EndPoint
{
if (!isInputShutdown())
shutdownInput();
else if (isOutputShutdown())
if (isOutputShutdown())
_channel.close();
}
}
catch (IOException x)
{
LOG.debug(x);
LOG.debug(x.toString());
LOG.ignore(x);
try
{
close();
if (_channel.isOpen())
_channel.close();
}
catch (IOException xx)
catch (Exception xx)
{
LOG.ignore(xx);
}
@ -293,20 +339,6 @@ public class ChannelEndPoint implements EndPoint
}
else
{
if (header!=null)
{
if (buffer!=null && buffer.length()>0 && header.space()>buffer.length())
{
header.put(buffer);
buffer.clear();
}
if (trailer!=null && trailer.length()>0 && header.space()>trailer.length())
{
header.put(trailer);
trailer.clear();
}
}
// flush header
if (header!=null && header.length()>0)
length=flush(header);
@ -478,24 +510,6 @@ public class ChannelEndPoint implements EndPoint
{
}
/* ------------------------------------------------------------ */
public boolean isBufferingInput()
{
return false;
}
/* ------------------------------------------------------------ */
public boolean isBufferingOutput()
{
return false;
}
/* ------------------------------------------------------------ */
public boolean isBufferred()
{
return false;
}
/* ------------------------------------------------------------ */
public int getMaxIdleTime()
{

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