Merge branch 'jetty-9' of ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project into jetty-9

This commit is contained in:
Joakim Erdfelt 2012-08-03 08:49:53 -07:00
commit 03521a9a99
161 changed files with 3105 additions and 3255 deletions

View File

@ -30,7 +30,6 @@ import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.RequestLogHandler;
import org.eclipse.jetty.server.handler.StatisticsHandler;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
@ -42,7 +41,12 @@ public class LikeJettyXml
String jetty_home = System.getProperty("jetty.home","../jetty-distribution/target/distribution");
System.setProperty("jetty.home",jetty_home);
Server server = new Server();
// Setup Threadpool
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(500);
Server server = new Server(threadPool);
server.manage(threadPool);
server.setDumpAfterStart(true);
server.setDumpBeforeStop(true);
@ -53,24 +57,19 @@ public class LikeJettyXml
server.addBean(mbContainer,true);
mbContainer.addBean(new Log());
// Setup Threadpool
QueuedThreadPool threadPool = new QueuedThreadPool();
threadPool.setMaxThreads(500);
server.setThreadPool(threadPool);
// Setup Connectors
SelectChannelConnector connector = new SelectChannelConnector();
SelectChannelConnector connector = new SelectChannelConnector(server);
connector.setPort(8080);
connector.setIdleTimeout(30000);
connector.setConfidentialPort(8443);
connector.getConnectionFactory().getHttpConfig().setConfidentialPort(8443);
// TODO connector.setStatsOn(false);
server.setConnectors(new Connector[]
{ connector });
SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector();
SelectChannelConnector ssl_connector = new SelectChannelConnector(server,true);
ssl_connector.setPort(8443);
SslContextFactory cf = ssl_connector.getSslContextFactory();
SslContextFactory cf = ssl_connector.getConnectionFactory().getSslContextFactory();
cf.setKeyStorePath(jetty_home + "/etc/keystore");
cf.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
cf.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");

View File

@ -16,9 +16,7 @@ package org.eclipse.jetty.embedded;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
/* ------------------------------------------------------------ */
/**
@ -31,22 +29,20 @@ public class ManyConnectors
{
Server server = new Server();
SelectChannelConnector connector0 = new SelectChannelConnector();
SelectChannelConnector connector0 = new SelectChannelConnector(server);
connector0.setPort(8080);
connector0.setIdleTimeout(30000);
connector0.setRequestHeaderSize(8192);
SelectChannelConnector connector1 = new SelectChannelConnector();
SelectChannelConnector connector1 = new SelectChannelConnector(server);
connector1.setHost("127.0.0.1");
connector1.setPort(8888);
connector1.setExecutor(new QueuedThreadPool(20));
connector1.setName("admin");
SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector();
SelectChannelConnector ssl_connector = new SelectChannelConnector(server,true);
String jetty_home = System.getProperty("jetty.home","../jetty-distribution/target/distribution");
System.setProperty("jetty.home",jetty_home);
ssl_connector.setPort(8443);
SslContextFactory cf = ssl_connector.getSslContextFactory();
SslContextFactory cf = ssl_connector.getConnectionFactory().getSslContextFactory();
cf.setKeyStorePath(jetty_home + "/etc/keystore");
cf.setKeyStorePassword("OBF:1vny1zlo1x8e1vnw1vn61x8g1zlu1vn4");
cf.setKeyManagerPassword("OBF:1u2u1wml1z7s1z7a1wnl1u2g");

View File

@ -15,10 +15,10 @@ package org.eclipse.jetty.embedded;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.server.SelectChannelConnector;
/* ------------------------------------------------------------ */
/**
@ -37,7 +37,7 @@ public class ManyContexts
public static void main(String[] args) throws Exception
{
Server server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
SelectChannelConnector connector = new SelectChannelConnector(server);
connector.setPort(8080);
server.setConnectors(new Connector[]
{ connector });

View File

@ -23,7 +23,6 @@ import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.log.Log;
public class ManyServletContexts
{

View File

@ -14,8 +14,8 @@
package org.eclipse.jetty.embedded;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.webapp.WebAppContext;
public class OneWebApp
@ -24,7 +24,7 @@ public class OneWebApp
{
Server server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
SelectChannelConnector connector = new SelectChannelConnector(server);
connector.setPort(Integer.getInteger("jetty.port",8080).intValue());
server.setConnectors(new Connector[]
{ connector });

View File

@ -27,13 +27,13 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.LocalHttpConnector;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.GzipHandler;
import org.eclipse.jetty.http.HttpTester;
import org.eclipse.jetty.util.IO;
import org.junit.After;
import org.junit.Before;
@ -56,14 +56,13 @@ public class GzipHandlerTest
"et cursus magna. Donec orci enim, molestie a lobortis eu, imperdiet vitae neque.";
private Server _server;
private LocalHttpConnector _connector;
private LocalConnector _connector;
@Before
public void init() throws Exception
{
_server = new Server();
_connector = new LocalHttpConnector();
_connector = new LocalConnector(_server);
_server.addConnector(_connector);
Handler testHandler = new AbstractHandler()

View File

@ -21,6 +21,16 @@
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -23,26 +23,26 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* <p>A convenience base implementation of {@link AsyncConnection}.</p>
* <p>This class uses the capabilities of the {@link AsyncEndPoint} API to provide a
* <p>A convenience base implementation of {@link Connection}.</p>
* <p>This class uses the capabilities of the {@link EndPoint} API to provide a
* more traditional style of async reading. A call to {@link #fillInterested()}
* will schedule a callback to {@link #onFillable()} or {@link #onFillInterestedFailed(Throwable)}
* as appropriate.</p>
*/
public abstract class AbstractAsyncConnection implements AsyncConnection
public abstract class AbstractConnection implements Connection
{
private static final Logger LOG = Log.getLogger(AbstractAsyncConnection.class);
private static final Logger LOG = Log.getLogger(AbstractConnection.class);
private final AtomicBoolean _readInterested = new AtomicBoolean();
private final AsyncEndPoint _endp;
private final EndPoint _endp;
private final Callback<Void> _readCallback;
public AbstractAsyncConnection(AsyncEndPoint endp, Executor executor)
public AbstractConnection(EndPoint endp, Executor executor)
{
this(endp, executor, false);
}
public AbstractAsyncConnection(AsyncEndPoint endp, Executor executor, final boolean executeOnlyFailure)
public AbstractConnection(EndPoint endp, Executor executor, final boolean executeOnlyFailure)
{
if (executor == null)
throw new IllegalArgumentException("Executor must not be null!");
@ -72,7 +72,7 @@ public abstract class AbstractAsyncConnection implements AsyncConnection
@Override
public String toString()
{
return String.format("%s@%x", getClass().getSimpleName(), AbstractAsyncConnection.this.hashCode());
return String.format("%s@%x", getClass().getSimpleName(), AbstractConnection.this.hashCode());
}
};
}
@ -130,16 +130,16 @@ public abstract class AbstractAsyncConnection implements AsyncConnection
public void onOpen()
{
LOG.debug("{} opened",this);
fillInterested();
}
@Override
public void onClose()
{
LOG.debug("{} closed",this);
}
@Override
public AsyncEndPoint getEndPoint()
public EndPoint getEndPoint()
{
return _endp;
}

View File

@ -1,20 +1,67 @@
package org.eclipse.jetty.io;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ReadPendingException;
import java.nio.channels.WritePendingException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public abstract class AbstractEndPoint implements EndPoint
{
private static final Logger LOG = Log.getLogger(AbstractEndPoint.class);
private final long _created=System.currentTimeMillis();
private final InetSocketAddress _local;
private final InetSocketAddress _remote;
private final ScheduledExecutorService _scheduler;
private final AtomicReference<Future<?>> _timeout = new AtomicReference<>();
private final Runnable _idleTask = new Runnable()
{
@Override
public void run()
{
long idleLeft=checkIdleTimeout();
if (idleLeft>=0)
scheduleIdleTimeout(idleLeft > 0 ? idleLeft : getIdleTimeout());
}
};
private volatile long _idleTimeout;
private volatile long _idleTimestamp=System.currentTimeMillis();
private volatile Connection _connection;
private final FillInterest _fillInterest = new FillInterest()
{
@Override
protected boolean needsFill() throws IOException
{
return AbstractEndPoint.this.needsFill();
}
};
private final WriteFlusher _writeFlusher = new WriteFlusher(this)
{
@Override
protected void onIncompleteFlushed()
{
AbstractEndPoint.this.onIncompleteFlush();
}
};
protected AbstractEndPoint(InetSocketAddress local,InetSocketAddress remote)
protected AbstractEndPoint(ScheduledExecutorService scheduler,InetSocketAddress local,InetSocketAddress remote)
{
_local=local;
_remote=remote;
_scheduler=scheduler;
}
@Override
@ -58,15 +105,117 @@ public abstract class AbstractEndPoint implements EndPoint
_idleTimestamp=System.currentTimeMillis();
}
@Override
public Connection getConnection()
{
return _connection;
}
@Override
public void setConnection(Connection connection)
{
_connection = connection;
}
@Override
public void onOpen()
{
LOG.debug("onOpen {}",this);
}
@Override
public void onClose()
{
LOG.debug("onClose {}",this);
_writeFlusher.onClose();
_fillInterest.onClose();
}
@Override
public <C> void fillInterested(C context, Callback<C> callback) throws IllegalStateException
{
_fillInterest.register(context, callback);
}
@Override
public <C> void write(C context, Callback<C> callback, ByteBuffer... buffers) throws IllegalStateException
{
_writeFlusher.write(context, callback, buffers);
}
protected abstract void onIncompleteFlush();
protected abstract boolean needsFill() throws IOException;
protected FillInterest getFillInterest()
{
return _fillInterest;
}
protected WriteFlusher getWriteFlusher()
{
return _writeFlusher;
}
protected void scheduleIdleTimeout(long delay)
{
Future<?> newTimeout = null;
if (isOpen() && delay > 0 && _scheduler!=null)
newTimeout = _scheduler.schedule(_idleTask, delay, TimeUnit.MILLISECONDS);
Future<?> oldTimeout = _timeout.getAndSet(newTimeout);
if (oldTimeout != null)
oldTimeout.cancel(false);
}
protected long checkIdleTimeout()
{
if (isOpen())
{
long idleTimestamp = getIdleTimestamp();
long idleTimeout = getIdleTimeout();
long idleElapsed = System.currentTimeMillis() - idleTimestamp;
long idleLeft = idleTimeout - idleElapsed;
LOG.debug("{} idle timeout check, elapsed: {} ms, remaining: {} ms", this, idleElapsed, idleLeft);
if (isOutputShutdown() || _fillInterest.isInterested() || _writeFlusher.isInProgress())
{
if (idleTimestamp != 0 && idleTimeout > 0)
{
if (idleLeft <= 0)
{
LOG.debug("{} idle timeout expired", this);
TimeoutException timeout = new TimeoutException("Idle timeout expired: " + idleElapsed + "/" + idleTimeout + " ms");
_fillInterest.onFail(timeout);
_writeFlusher.onFail(timeout);
if (isOutputShutdown())
close();
notIdle();
}
}
}
return idleLeft>=0?idleLeft:0;
}
return -1;
}
@Override
public String toString()
{
return String.format("%s@%x{%s<r-l>%s,o=%b,os=%b}",
return String.format("%s@%x{%s<r-l>%s,o=%b,is=%b,os=%b,fi=%s,wf=%s}{%s}",
getClass().getSimpleName(),
hashCode(),
getRemoteAddress(),
getLocalAddress(),
isOpen(),
isOutputShutdown());
isInputShutdown(),
isOutputShutdown(),
_fillInterest,
_writeFlusher,
getConnection());
}
}

View File

@ -1,172 +0,0 @@
package org.eclipse.jetty.io;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
public class AsyncByteArrayEndPoint extends ByteArrayEndPoint implements AsyncEndPoint, Runnable
{
private static final Logger LOG = Log.getLogger(AsyncByteArrayEndPoint.class);
private final ReadInterest _readInterest = new ReadInterest()
{
@Override
protected boolean needsFill() throws IOException
{
if (_closed)
throw new ClosedChannelException();
return _in == null || BufferUtil.hasContent(_in);
}
};
private final WriteFlusher _writeFlusher = new WriteFlusher(this)
{
@Override
protected void onIncompleteFlushed()
{
// Don't need to do anything here as takeOutput does the signalling.
}
};
private final AtomicReference<Future<?>> _timeout = new AtomicReference<>();
private final ScheduledExecutorService _scheduler;
private volatile AsyncConnection _connection;
public AsyncByteArrayEndPoint(ScheduledExecutorService scheduler, long idleTimeout)
{
_scheduler = scheduler;
setIdleTimeout(idleTimeout);
}
public AsyncByteArrayEndPoint(ScheduledExecutorService timer, long idleTimeout, byte[] input, int outputSize)
{
super(input, outputSize);
_scheduler = timer;
setIdleTimeout(idleTimeout);
}
public AsyncByteArrayEndPoint(ScheduledExecutorService timer, long idleTimeout, String input, int outputSize)
{
super(input, outputSize);
_scheduler = timer;
setIdleTimeout(idleTimeout);
}
@Override
public void setIdleTimeout(long idleTimeout)
{
super.setIdleTimeout(idleTimeout);
scheduleIdleTimeout(idleTimeout);
}
private void scheduleIdleTimeout(long delay)
{
Future<?> newTimeout = isOpen() && delay > 0 ? _scheduler.schedule(this, delay, TimeUnit.MILLISECONDS) : null;
Future<?> oldTimeout = _timeout.getAndSet(newTimeout);
if (oldTimeout != null)
oldTimeout.cancel(false);
}
@Override
public void run()
{
if (isOpen())
{
long idleTimestamp = getIdleTimestamp();
long idleTimeout = getIdleTimeout();
long idleElapsed = System.currentTimeMillis() - idleTimestamp;
long idleLeft = idleTimeout - idleElapsed;
if (isOutputShutdown() || _readInterest.isInterested() || _writeFlusher.isWriting())
{
if (idleTimestamp != 0 && idleTimeout > 0)
{
if (idleLeft < 0)
{
if (isOutputShutdown())
close();
notIdle();
TimeoutException timeout = new TimeoutException("Idle timeout expired: " + idleElapsed + "/" + idleTimeout + " ms");
_readInterest.failed(timeout);
_writeFlusher.failed(timeout);
}
}
}
scheduleIdleTimeout(idleLeft > 0 ? idleLeft : idleTimeout);
}
}
@Override
public void setInput(ByteBuffer in)
{
super.setInput(in);
if (in == null || BufferUtil.hasContent(in))
_readInterest.readable();
}
@Override
public ByteBuffer takeOutput()
{
ByteBuffer b = super.takeOutput();
_writeFlusher.completeWrite();
return b;
}
@Override
public void setOutput(ByteBuffer out)
{
super.setOutput(out);
_writeFlusher.completeWrite();
}
@Override
public void reset()
{
_readInterest.close();
_writeFlusher.close();
super.reset();
}
@Override
public <C> void fillInterested(C context, Callback<C> callback) throws IllegalStateException
{
_readInterest.register(context, callback);
}
@Override
public <C> void write(C context, Callback<C> callback, ByteBuffer... buffers) throws IllegalStateException
{
_writeFlusher.write(context, callback, buffers);
}
@Override
public AsyncConnection getAsyncConnection()
{
return _connection;
}
@Override
public void setAsyncConnection(AsyncConnection connection)
{
_connection = connection;
}
@Override
public void onOpen()
{
}
@Override
public void onClose()
{
}
}

View File

@ -1,129 +0,0 @@
// ========================================================================
// Copyright (c) 2004-2012 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;
import java.nio.ByteBuffer;
import java.nio.channels.ReadPendingException;
import java.nio.channels.WritePendingException;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.ExecutorCallback;
import org.eclipse.jetty.util.FutureCallback;
/**
* <p>{@link AsyncEndPoint} add asynchronous scheduling methods to {@link EndPoint}.</p>
* <p>The design of these has been influenced by NIO.2 Futures and Completion
* handlers, but does not use those actual interfaces because they have
* some inefficiencies.</p>
* <p>This class will frequently be used in conjunction with some of the utility
* implementations of {@link Callback}, such as {@link FutureCallback} and
* {@link ExecutorCallback}. Examples are:</p>
*
* <h3>Blocking Read</h3>
* <p>A FutureCallback can be used to block until an endpoint is ready to be filled
* from:
* <blockquote><pre>
* FutureCallback&lt;String&gt; future = new FutureCallback&lt;&gt;();
* endpoint.fillInterested("ContextObj",future);
* ...
* String context = future.get(); // This blocks
* int filled=endpoint.fill(mybuffer);
* </pre></blockquote></p>
*
* <h3>Dispatched Read</h3>
* <p>By using a different callback, the read can be done asynchronously in its own dispatched thread:
* <blockquote><pre>
* endpoint.fillInterested("ContextObj",new ExecutorCallback&lt;String&gt;(executor)
* {
* public void onCompleted(String context)
* {
* int filled=endpoint.fill(mybuffer);
* ...
* }
* public void onFailed(String context,Throwable cause) {...}
* });
* </pre></blockquote></p>
* <p>The executor callback can also be customized to not dispatch in some circumstances when
* it knows it can use the callback thread and does not need to dispatch.</p>
*
* <h3>Blocking Write</h3>
* <p>The write contract is that the callback complete is not called until all data has been
* written or there is a failure. For blocking this looks like:
* <blockquote><pre>
* FutureCallback&lt;String&gt; future = new FutureCallback&lt;&gt;();
* endpoint.write("ContextObj",future,headerBuffer,contentBuffer);
* String context = future.get(); // This blocks
* </pre></blockquote></p>
*
* <h3>Dispatched Write</h3>
* <p>Note also that multiple buffers may be passed in write so that gather writes
* can be done:
* <blockquote><pre>
* endpoint.write("ContextObj",new ExecutorCallback&lt;String&gt;(executor)
* {
* public void onCompleted(String context)
* {
* int filled=endpoint.fill(mybuffer);
* ...
* }
* public void onFailed(String context,Throwable cause) {...}
* },headerBuffer,contentBuffer);
* </pre></blockquote></p>
*/
public interface AsyncEndPoint extends EndPoint
{
/**
* <p>Requests callback methods to be invoked when a call to {@link #fill(ByteBuffer)} would return data or EOF.</p>
*
* @param context the context to return via the callback
* @param callback the callback to call when an error occurs or we are readable.
* @throws ReadPendingException if another read operation is concurrent.
*/
<C> void fillInterested(C context, Callback<C> callback) throws ReadPendingException;
/**
* <p>Writes the given buffers via {@link #flush(ByteBuffer...)} and invokes callback methods when either
* all the data has been flushed or an error occurs.</p>
*
* @param context the context to return via the callback
* @param callback the callback to call when an error occurs or the write completed.
* @param buffers one or more {@link ByteBuffer}s that will be flushed.
* @throws WritePendingException if another write operation is concurrent.
*/
<C> void write(C context, Callback<C> callback, ByteBuffer... buffers) throws WritePendingException;
/**
* @return the {@link AsyncConnection} associated with this {@link AsyncEndPoint}
* @see #setAsyncConnection(AsyncConnection)
*/
AsyncConnection getAsyncConnection();
/**
* @param connection the {@link AsyncConnection} associated with this {@link AsyncEndPoint}
* @see #getAsyncConnection()
*/
void setAsyncConnection(AsyncConnection connection);
/**
* <p>Callback method invoked when this {@link AsyncEndPoint} is opened.</p>
* @see #onClose()
*/
void onOpen();
/**
* <p>Callback method invoked when this {@link AsyncEndPoint} is close.</p>
* @see #onOpen()
*/
void onClose();
}

View File

@ -16,10 +16,19 @@ package org.eclipse.jetty.io;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.charset.Charset;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
@ -28,14 +37,16 @@ import org.eclipse.jetty.util.StringUtil;
*/
public class ByteArrayEndPoint extends AbstractEndPoint
{
static final Logger LOG = Log.getLogger(ByteArrayEndPoint.class);
public final static InetSocketAddress NOIP=new InetSocketAddress(0);
protected ByteBuffer _in;
protected ByteBuffer _out;
protected boolean _ishut;
protected boolean _oshut;
protected boolean _closed;
protected boolean _growOutput;
/* ------------------------------------------------------------ */
/**
@ -43,9 +54,7 @@ public class ByteArrayEndPoint extends AbstractEndPoint
*/
public ByteArrayEndPoint()
{
super(NOIP,NOIP);
_in=BufferUtil.EMPTY_BUFFER;
_out=BufferUtil.allocate(1024);
this(null,0,null,null);
}
/* ------------------------------------------------------------ */
@ -54,9 +63,7 @@ public class ByteArrayEndPoint extends AbstractEndPoint
*/
public ByteArrayEndPoint(byte[] input, int outputSize)
{
super(NOIP,NOIP);
_in=input==null?null:ByteBuffer.wrap(input);
_out=BufferUtil.allocate(outputSize);
this(null,0,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
}
/* ------------------------------------------------------------ */
@ -65,11 +72,55 @@ public class ByteArrayEndPoint extends AbstractEndPoint
*/
public ByteArrayEndPoint(String input, int outputSize)
{
super(NOIP,NOIP);
setInput(input);
_out=BufferUtil.allocate(outputSize);
this(null,0,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
}
/* ------------------------------------------------------------ */
public ByteArrayEndPoint(ScheduledExecutorService timer, long idleTimeoutMs)
{
this(timer,idleTimeoutMs,null,null);
}
/* ------------------------------------------------------------ */
public ByteArrayEndPoint(ScheduledExecutorService timer, long idleTimeoutMs, byte[] input, int outputSize)
{
this(timer,idleTimeoutMs,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
}
/* ------------------------------------------------------------ */
public ByteArrayEndPoint(ScheduledExecutorService timer, long idleTimeoutMs, String input, int outputSize)
{
this(timer,idleTimeoutMs,input!=null?BufferUtil.toBuffer(input):null,BufferUtil.allocate(outputSize));
}
/* ------------------------------------------------------------ */
public ByteArrayEndPoint(ScheduledExecutorService timer, long idleTimeoutMs, ByteBuffer input, ByteBuffer output)
{
super(timer,NOIP,NOIP);
_in=input==null?BufferUtil.EMPTY_BUFFER:input;
_out=output==null?BufferUtil.allocate(1024):output;
setIdleTimeout(idleTimeoutMs);
}
/* ------------------------------------------------------------ */
@Override
protected void onIncompleteFlush()
{
// Don't need to do anything here as takeOutput does the signalling.
}
/* ------------------------------------------------------------ */
@Override
protected boolean needsFill() throws IOException
{
if (_closed)
throw new ClosedChannelException();
return _in == null || BufferUtil.hasContent(_in);
}
/* ------------------------------------------------------------ */
/**
@ -95,6 +146,8 @@ public class ByteArrayEndPoint extends AbstractEndPoint
public void setInput(ByteBuffer in)
{
_in = in;
if (in == null || BufferUtil.hasContent(in))
getFillInterest().fillable();
}
/* ------------------------------------------------------------ */
@ -135,6 +188,7 @@ public class ByteArrayEndPoint extends AbstractEndPoint
{
ByteBuffer b=_out;
_out=BufferUtil.allocate(b.capacity());
getWriteFlusher().completeWrite();
return b;
}
@ -164,6 +218,7 @@ public class ByteArrayEndPoint extends AbstractEndPoint
public void setOutput(ByteBuffer out)
{
_out = out;
getWriteFlusher().completeWrite();
}
/* ------------------------------------------------------------ */
@ -195,7 +250,7 @@ public class ByteArrayEndPoint extends AbstractEndPoint
}
/* ------------------------------------------------------------ */
private void shutdownInput() throws IOException
private void shutdownInput()
{
_ishut=true;
if (_oshut)
@ -222,7 +277,6 @@ public class ByteArrayEndPoint extends AbstractEndPoint
public void close()
{
_closed=true;
// TODO: for sbordet to fix - onClose(); Moved invocation to AsycnByteArrayEndPoint for now (GW)
}
/* ------------------------------------------------------------ */
@ -299,6 +353,8 @@ public class ByteArrayEndPoint extends AbstractEndPoint
*/
public void reset()
{
getFillInterest().onClose();
getWriteFlusher().onClose();
_ishut=false;
_oshut=false;
_closed=false;
@ -334,5 +390,14 @@ public class ByteArrayEndPoint extends AbstractEndPoint
_growOutput=growOutput;
}
/* ------------------------------------------------------------ */
@Override
public void setIdleTimeout(long idleTimeout)
{
super.setIdleTimeout(idleTimeout);
scheduleIdleTimeout(idleTimeout);
}
}

View File

@ -22,10 +22,13 @@ import java.nio.ByteBuffer;
import java.nio.channels.ByteChannel;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ReadPendingException;
import java.nio.channels.SocketChannel;
import java.util.concurrent.BrokenBarrierException;
import java.nio.channels.WritePendingException;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -42,10 +45,11 @@ public class ChannelEndPoint extends AbstractEndPoint
private volatile boolean _ishut;
private volatile boolean _oshut;
public ChannelEndPoint(SocketChannel channel) throws IOException
public ChannelEndPoint(ScheduledExecutorService scheduler,SocketChannel channel) throws IOException
{
super((InetSocketAddress)channel.socket().getLocalSocketAddress(),
(InetSocketAddress)channel.socket().getRemoteSocketAddress());
super(scheduler,
(InetSocketAddress)channel.socket().getLocalSocketAddress(),
(InetSocketAddress)channel.socket().getRemoteSocketAddress());
_channel = channel;
_socket=channel.socket();
}
@ -195,4 +199,16 @@ public class ChannelEndPoint extends AbstractEndPoint
{
return _socket;
}
@Override
protected void onIncompleteFlush()
{
throw new UnsupportedOperationException();
}
@Override
protected boolean needsFill() throws IOException
{
throw new UnsupportedOperationException();
}
}

View File

@ -16,27 +16,27 @@ package org.eclipse.jetty.io;
import org.eclipse.jetty.util.Callback;
/**
* <p>An {@link AsyncConnection} is associated to an {@link AsyncEndPoint} so that I/O events
* happening on the {@link AsyncEndPoint} can be processed by the {@link AsyncConnection}.</p>
* <p>A typical implementation of {@link AsyncConnection} overrides {@link #onOpen()} to
* {@link AsyncEndPoint#fillInterested(Object, Callback) set read interest} on the {@link AsyncEndPoint},
* and when the {@link AsyncEndPoint} signals read readyness, this {@link AsyncConnection} can
* <p>An {@link Connection} is associated to an {@link EndPoint} so that I/O events
* happening on the {@link EndPoint} can be processed by the {@link Connection}.</p>
* <p>A typical implementation of {@link Connection} overrides {@link #onOpen()} to
* {@link EndPoint#fillInterested(Object, Callback) set read interest} on the {@link EndPoint},
* and when the {@link EndPoint} signals read readyness, this {@link Connection} can
* read bytes from the network and interpret them.</p>
*/
public interface AsyncConnection
public interface Connection
{
/**
* <p>Callback method invoked when this {@link AsyncConnection} is opened.</p>
* <p>Callback method invoked when this {@link Connection} is opened.</p>
*/
void onOpen();
/**
* <p>Callback method invoked when this {@link AsyncConnection} is closed.</p>
* <p>Callback method invoked when this {@link Connection} is closed.</p>
*/
void onClose();
/**
* @return the {@link AsyncEndPoint} associated with this {@link AsyncConnection}
* @return the {@link EndPoint} associated with this {@link Connection}
*/
AsyncEndPoint getEndPoint();
EndPoint getEndPoint();
}

View File

@ -17,12 +17,78 @@ import java.io.Closeable;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ReadPendingException;
import java.nio.channels.WritePendingException;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.ExecutorCallback;
import org.eclipse.jetty.util.FutureCallback;
/**
*
* A transport EndPoint
*
* <h3>Asynchronous Methods</h3>
* <p>The asynchronous scheduling methods of {@link EndPoint}
* has been influenced by NIO.2 Futures and Completion
* handlers, but does not use those actual interfaces because they have
* some inefficiencies.</p>
* <p>This class will frequently be used in conjunction with some of the utility
* implementations of {@link Callback}, such as {@link FutureCallback} and
* {@link ExecutorCallback}. Examples are:</p>
*
* <h3>Blocking Read</h3>
* <p>A FutureCallback can be used to block until an endpoint is ready to be filled
* from:
* <blockquote><pre>
* FutureCallback&lt;String&gt; future = new FutureCallback&lt;&gt;();
* endpoint.fillInterested("ContextObj",future);
* ...
* String context = future.get(); // This blocks
* int filled=endpoint.fill(mybuffer);
* </pre></blockquote></p>
*
* <h3>Dispatched Read</h3>
* <p>By using a different callback, the read can be done asynchronously in its own dispatched thread:
* <blockquote><pre>
* endpoint.fillInterested("ContextObj",new ExecutorCallback&lt;String&gt;(executor)
* {
* public void onCompleted(String context)
* {
* int filled=endpoint.fill(mybuffer);
* ...
* }
* public void onFailed(String context,Throwable cause) {...}
* });
* </pre></blockquote></p>
* <p>The executor callback can also be customized to not dispatch in some circumstances when
* it knows it can use the callback thread and does not need to dispatch.</p>
*
* <h3>Blocking Write</h3>
* <p>The write contract is that the callback complete is not called until all data has been
* written or there is a failure. For blocking this looks like:
* <blockquote><pre>
* FutureCallback&lt;String&gt; future = new FutureCallback&lt;&gt;();
* endpoint.write("ContextObj",future,headerBuffer,contentBuffer);
* String context = future.get(); // This blocks
* </pre></blockquote></p>
*
* <h3>Dispatched Write</h3>
* <p>Note also that multiple buffers may be passed in write so that gather writes
* can be done:
* <blockquote><pre>
* endpoint.write("ContextObj",new ExecutorCallback&lt;String&gt;(executor)
* {
* public void onCompleted(String context)
* {
* int filled=endpoint.fill(mybuffer);
* ...
* }
* public void onFailed(String context,Throwable cause) {...}
* },headerBuffer,contentBuffer);
* </pre></blockquote></p>
*/
public interface EndPoint extends Closeable
{
@ -126,5 +192,48 @@ public interface EndPoint extends Closeable
void setIdleTimeout(long idleTimeout);
/**
* <p>Requests callback methods to be invoked when a call to {@link #fill(ByteBuffer)} would return data or EOF.</p>
*
* @param context the context to return via the callback
* @param callback the callback to call when an error occurs or we are readable.
* @throws ReadPendingException if another read operation is concurrent.
*/
<C> void fillInterested(C context, Callback<C> callback) throws ReadPendingException;
/**
* <p>Writes the given buffers via {@link #flush(ByteBuffer...)} and invokes callback methods when either
* all the data has been flushed or an error occurs.</p>
*
* @param context the context to return via the callback
* @param callback the callback to call when an error occurs or the write completed.
* @param buffers one or more {@link ByteBuffer}s that will be flushed.
* @throws WritePendingException if another write operation is concurrent.
*/
<C> void write(C context, Callback<C> callback, ByteBuffer... buffers) throws WritePendingException;
/**
* @return the {@link Connection} associated with this {@link EndPoint}
* @see #setConnection(Connection)
*/
Connection getConnection();
/**
* @param connection the {@link Connection} associated with this {@link EndPoint}
* @see #getConnection()
*/
void setConnection(Connection connection);
/**
* <p>Callback method invoked when this {@link EndPoint} is opened.</p>
* @see #onClose()
*/
void onOpen();
/**
* <p>Callback method invoked when this {@link EndPoint} is close.</p>
* @see #onOpen()
*/
void onClose();
}

View File

@ -10,25 +10,25 @@ import org.eclipse.jetty.util.Callback;
/* ------------------------------------------------------------ */
/**
* A Utility class to help implement {@link AsyncEndPoint#fillInterested(Object, Callback)}
* A Utility class to help implement {@link EndPoint#fillInterested(Object, Callback)}
* by keeping state and calling the context and callback objects.
*
*/
public abstract class ReadInterest
public abstract class FillInterest
{
private final AtomicBoolean _interested = new AtomicBoolean(false);
private volatile Callback<Object> _callback;
private Object _context;
/* ------------------------------------------------------------ */
protected ReadInterest()
protected FillInterest()
{
}
/* ------------------------------------------------------------ */
/** Call to register interest in a callback when a read is possible.
* The callback will be called either immediately if {@link #needsFill()}
* returns true or eventually once {@link #readable()} is called.
* returns true or eventually once {@link #fillable()} is called.
* @param context
* @param callback
* @throws ReadPendingException
@ -42,18 +42,18 @@ public abstract class ReadInterest
try
{
if (needsFill())
readable();
fillable();
}
catch(IOException e)
{
failed(e);
onFail(e);
}
}
/* ------------------------------------------------------------ */
/** Call to signal that a read is now possible.
*/
public void readable()
public void fillable()
{
if (_interested.compareAndSet(true,false))
{
@ -77,7 +77,7 @@ public abstract class ReadInterest
/* ------------------------------------------------------------ */
/** Call to signal a failure to a registered interest
*/
public void failed(Throwable cause)
public void onFail(Throwable cause)
{
if (_interested.compareAndSet(true,false))
{
@ -90,7 +90,7 @@ public abstract class ReadInterest
}
/* ------------------------------------------------------------ */
public void close()
public void onClose()
{
if (_interested.compareAndSet(true,false))
{
@ -106,14 +106,14 @@ public abstract class ReadInterest
@Override
public String toString()
{
return String.format("ReadInterest@%x{%b,%s,%s}",hashCode(),_interested.get(),_callback,_context);
return String.format("FillInterest@%x{%b,%s,%s}",hashCode(),_interested.get(),_callback,_context);
}
/* ------------------------------------------------------------ */
/** Register the read interest
* Abstract method to be implemented by the Specific ReadInterest to
* enquire if a read is immediately possible and if not to schedule a future
* call to {@link #readable()} or {@link #failed(Throwable)}
* call to {@link #fillable()} or {@link #onFail(Throwable)}
* @return true if a read is possible
* @throws IOException
*/

View File

@ -32,43 +32,44 @@ import org.eclipse.jetty.util.log.Logger;
/**
* An ChannelEndpoint that can be scheduled by {@link SelectorManager}.
*/
public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable, SelectorManager.SelectableAsyncEndPoint
public class SelectChannelEndPoint extends ChannelEndPoint implements SelectorManager.SelectableEndPoint
{
public static final Logger LOG = Log.getLogger(SelectChannelEndPoint.class);
private final AtomicReference<Future<?>> _timeout = new AtomicReference<>();
private final Runnable _idleTask = new Runnable()
private final Runnable _updateTask = new Runnable()
{
@Override
public void run()
{
checkIdleTimeout();
try
{
if (getChannel().isOpen())
{
int oldInterestOps = _key.interestOps();
int newInterestOps = _interestOps;
if (newInterestOps != oldInterestOps)
setKeyInterests(oldInterestOps, newInterestOps);
}
}
catch (CancelledKeyException x)
{
LOG.debug("Ignoring key update for concurrently closed channel {}", this);
close();
}
catch (Exception x)
{
LOG.warn("Ignoring key update for " + this, x);
close();
}
}
};
/**
* true if {@link ManagedSelector#destroyEndPoint(AsyncEndPoint)} has not been called
* true if {@link ManagedSelector#destroyEndPoint(EndPoint)} has not been called
*/
private final AtomicBoolean _open = new AtomicBoolean();
private final ReadInterest _readInterest = new ReadInterest()
{
@Override
protected boolean needsFill()
{
return SelectChannelEndPoint.this.needsFill();
}
};
private final WriteFlusher _writeFlusher = new WriteFlusher(this)
{
@Override
protected void onIncompleteFlushed()
{
SelectChannelEndPoint.this.onIncompleteFlush();
}
};
private final SelectorManager.ManagedSelector _selector;
private final SelectionKey _key;
private final ScheduledExecutorService _scheduler;
private volatile AsyncConnection _connection;
/**
* The desired value for {@link SelectionKey#interestOps()}
*/
@ -76,10 +77,9 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
public SelectChannelEndPoint(SocketChannel channel, ManagedSelector selector, SelectionKey key, ScheduledExecutorService scheduler, long idleTimeout) throws IOException
{
super(channel);
super(scheduler,channel);
_selector = selector;
_key = key;
_scheduler = scheduler;
setIdleTimeout(idleTimeout);
}
@ -90,57 +90,25 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
scheduleIdleTimeout(idleTimeout);
}
@Override
protected boolean needsFill()
{
updateLocalInterests(SelectionKey.OP_READ, true);
return false;
}
@Override
protected void onIncompleteFlush()
{
updateLocalInterests(SelectionKey.OP_WRITE, true);
}
private void scheduleIdleTimeout(long delay)
{
Future<?> newTimeout = null;
if (isOpen() && delay > 0)
{
LOG.debug("{} scheduling idle timeout in {} ms", this, delay);
newTimeout = _scheduler.schedule(_idleTask, delay, TimeUnit.MILLISECONDS);
}
else
{
LOG.debug("{} skipped scheduling idle timeout ({} ms)", this, delay);
}
Future<?> oldTimeout = _timeout.getAndSet(newTimeout);
if (oldTimeout != null)
oldTimeout.cancel(false);
}
@Override
public <C> void fillInterested(C context, Callback<C> callback) throws IllegalStateException
public void setConnection(Connection connection)
{
_readInterest.register(context, callback);
}
@Override
public <C> void write(C context, Callback<C> callback, ByteBuffer... buffers) throws IllegalStateException
{
_writeFlusher.write(context, callback, buffers);
}
@Override
public AsyncConnection getAsyncConnection()
{
return _connection;
}
@Override
public void setAsyncConnection(AsyncConnection connection)
{
AsyncConnection old = getAsyncConnection();
_connection = connection;
// TODO should this be on AbstractEndPoint?
Connection old = getConnection();
super.setConnection(connection);
if (old != null && old != connection)
_selector.getSelectorManager().connectionUpgraded(this, old);
}
@ -154,43 +122,11 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
setKeyInterests(oldInterestOps, newInterestOps);
updateLocalInterests(readyOps, false);
if (_key.isReadable())
_readInterest.readable();
getFillInterest().fillable();
if (_key.isWritable())
_writeFlusher.completeWrite();
getWriteFlusher().completeWrite();
}
private void checkIdleTimeout()
{
if (isOpen())
{
long idleTimestamp = getIdleTimestamp();
long idleTimeout = getIdleTimeout();
long idleElapsed = System.currentTimeMillis() - idleTimestamp;
long idleLeft = idleTimeout - idleElapsed;
LOG.debug("{} idle timeout check, elapsed: {} ms, remaining: {} ms", this, idleElapsed, idleLeft);
if (isOutputShutdown() || _readInterest.isInterested() || _writeFlusher.isWriting())
{
if (idleTimestamp != 0 && idleTimeout > 0)
{
if (idleLeft <= 0)
{
LOG.debug("{} idle timeout expired", this);
if (isOutputShutdown())
close();
notIdle();
TimeoutException timeout = new TimeoutException("Idle timeout expired: " + idleElapsed + "/" + idleTimeout + " ms");
_readInterest.failed(timeout);
_writeFlusher.failed(timeout);
}
}
}
scheduleIdleTimeout(idleLeft > 0 ? idleLeft : idleTimeout);
}
}
private void updateLocalInterests(int operation, boolean add)
{
@ -210,7 +146,7 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
{
_interestOps = newInterestOps;
LOG.debug("Local interests updated {} -> {} for {}", oldInterestOps, newInterestOps, this);
_selector.submit(this);
_selector.submit(_updateTask);
}
else
{
@ -218,30 +154,6 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
}
}
@Override
public void run()
{
try
{
if (getChannel().isOpen())
{
int oldInterestOps = _key.interestOps();
int newInterestOps = _interestOps;
if (newInterestOps != oldInterestOps)
setKeyInterests(oldInterestOps, newInterestOps);
}
}
catch (CancelledKeyException x)
{
LOG.debug("Ignoring key update for concurrently closed channel {}", this);
close();
}
catch (Exception x)
{
LOG.warn("Ignoring key update for " + this, x);
close();
}
}
private void setKeyInterests(int oldInterestOps, int newInterestOps)
{
@ -260,14 +172,14 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
@Override
public void onOpen()
{
super.onOpen();
_open.compareAndSet(false, true);
}
@Override
public void onClose()
{
_writeFlusher.close();
_readInterest.close();
super.onClose();
}
@Override
@ -288,8 +200,6 @@ public class SelectChannelEndPoint extends ChannelEndPoint implements Runnable,
{
keyString += "!";
}
return String.format("SCEP@%x{l(%s)<->r(%s),open=%b,ishut=%b,oshut=%b,i=%d%s,r=%s,w=%s}-{%s}",
hashCode(), getRemoteAddress(), getLocalAddress(), isOpen(), isInputShutdown(),
isOutputShutdown(), _interestOps, keyString, _readInterest, _writeFlusher, getAsyncConnection());
return String.format("%s{io=%d,k=%s}",_interestOps, keyString);
}
}

View File

@ -44,7 +44,7 @@ import org.eclipse.jetty.util.log.Logger;
* <p>{@link SelectorManager} manages a number of {@link ManagedSelector}s that
* simplify the non-blocking primitives provided by the JVM via the {@code java.nio} package.</p>
* <p>{@link SelectorManager} subclasses implement methods to return protocol-specific
* {@link AsyncEndPoint}s and {@link AsyncConnection}s.</p>
* {@link EndPoint}s and {@link Connection}s.</p>
*/
public abstract class SelectorManager extends AbstractLifeCycle implements Dumpable
{
@ -152,7 +152,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
*
* @param endpoint the endpoint being opened
*/
protected void endPointOpened(AsyncEndPoint endpoint)
protected void endPointOpened(EndPoint endpoint)
{
endpoint.onOpen();
}
@ -162,7 +162,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
*
* @param endpoint the endpoint being closed
*/
protected void endPointClosed(AsyncEndPoint endpoint)
protected void endPointClosed(EndPoint endpoint)
{
endpoint.onClose();
}
@ -172,7 +172,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
*
* @param connection the connection just opened
*/
public void connectionOpened(AsyncConnection connection)
public void connectionOpened(Connection connection)
{
connection.onOpen();
}
@ -182,7 +182,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
*
* @param connection the connection just closed
*/
public void connectionClosed(AsyncConnection connection)
public void connectionClosed(Connection connection)
{
connection.onClose();
}
@ -193,10 +193,10 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
* @param endpoint the endpoint holding the new connection
* @param oldConnection the previous connection
*/
public void connectionUpgraded(AsyncEndPoint endpoint, AsyncConnection oldConnection)
public void connectionUpgraded(EndPoint endpoint, Connection oldConnection)
{
connectionClosed(oldConnection);
connectionOpened(endpoint.getAsyncConnection());
connectionOpened(endpoint.getConnection());
}
/**
@ -213,7 +213,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
}
/**
* <p>Factory method to create {@link AsyncEndPoint}.</p>
* <p>Factory method to create {@link EndPoint}.</p>
* <p>This method is invoked as a result of the registration of a channel via {@link #connect(SocketChannel, Object)}
* or {@link #accept(SocketChannel)}.</p>
*
@ -222,20 +222,21 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
* @param selectionKey the selection key
* @return a new endpoint
* @throws IOException if the endPoint cannot be created
* @see #newConnection(SocketChannel, AsyncEndPoint, Object)
* @see #newConnection(SocketChannel, EndPoint, Object)
*/
protected abstract AsyncEndPoint newEndPoint(SocketChannel channel, SelectorManager.ManagedSelector selector, SelectionKey selectionKey) throws IOException;
protected abstract EndPoint newEndPoint(SocketChannel channel, SelectorManager.ManagedSelector selector, SelectionKey selectionKey) throws IOException;
/**
* <p>Factory method to create {@link AsyncConnection}.</p>
* <p>Factory method to create {@link Connection}.</p>
*
* @param channel the channel associated to the connection
* @param endpoint the endpoint
* @param attachment the attachment
* @return a new connection
* @throws IOException
* @see #newEndPoint(SocketChannel, ManagedSelector, SelectionKey)
*/
public abstract AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment);
public abstract Connection newConnection(SocketChannel channel, EndPoint endpoint, Object attachment) throws IOException;
@Override
public String dump()
@ -253,7 +254,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
/**
* <p>{@link ManagedSelector} wraps a {@link Selector} simplifying non-blocking operations on channels.</p>
* <p>{@link ManagedSelector} runs the select loop, which waits on {@link Selector#select()} until events
* happen for registered channels. When events happen, it notifies the {@link AsyncEndPoint} associated
* happen for registered channels. When events happen, it notifies the {@link EndPoint} associated
* with the channel.</p>
*/
public class ManagedSelector extends AbstractLifeCycle implements Runnable, Dumpable
@ -412,9 +413,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
Object attachment = key.attachment();
try
{
if (attachment instanceof SelectableAsyncEndPoint)
if (attachment instanceof SelectableEndPoint)
{
((SelectableAsyncEndPoint)attachment).onSelected();
((SelectableEndPoint)attachment).onSelected();
}
else if (key.isConnectable())
{
@ -426,7 +427,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
if (connected)
{
key.interestOps(0);
AsyncEndPoint endpoint = createEndPoint(channel, key);
EndPoint endpoint = createEndPoint(channel, key);
key.attach(endpoint);
}
else
@ -481,21 +482,21 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
_selector.wakeup();
}
private AsyncEndPoint createEndPoint(SocketChannel channel, SelectionKey selectionKey) throws IOException
private EndPoint createEndPoint(SocketChannel channel, SelectionKey selectionKey) throws IOException
{
AsyncEndPoint endPoint = newEndPoint(channel, this, selectionKey);
EndPoint endPoint = newEndPoint(channel, this, selectionKey);
endPointOpened(endPoint);
AsyncConnection asyncConnection = newConnection(channel, endPoint, selectionKey.attachment());
endPoint.setAsyncConnection(asyncConnection);
Connection asyncConnection = newConnection(channel, endPoint, selectionKey.attachment());
endPoint.setConnection(asyncConnection);
connectionOpened(asyncConnection);
LOG.debug("Created {}", endPoint);
return endPoint;
}
public void destroyEndPoint(AsyncEndPoint endPoint)
public void destroyEndPoint(EndPoint endPoint)
{
LOG.debug("Destroyed {}", endPoint);
connectionClosed(endPoint.getAsyncConnection());
connectionClosed(endPoint.getConnection());
endPointClosed(endPoint);
}
@ -607,7 +608,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
try
{
SelectionKey key = _channel.register(_selector, 0, null);
AsyncEndPoint endpoint = createEndPoint(_channel, key);
EndPoint endpoint = createEndPoint(_channel, key);
key.attach(endpoint);
}
catch (IOException x)
@ -684,10 +685,10 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
}
/**
* A {@link SelectableAsyncEndPoint} is an {@link AsyncEndPoint} that wish to be notified of
* A {@link SelectableEndPoint} is an {@link EndPoint} that wish to be notified of
* non-blocking events by the {@link ManagedSelector}.
*/
public interface SelectableAsyncEndPoint extends AsyncEndPoint
public interface SelectableEndPoint extends EndPoint
{
/**
* <p>Callback method invoked when a read or write events has been detected by the {@link ManagedSelector}

View File

@ -1,212 +1,438 @@
// ========================================================================
// Copyright (c) 2012-2012 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;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.WritePendingException;
import java.util.ConcurrentModificationException;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/**
* A Utility class to help implement {@link AsyncEndPoint#write(Object, Callback, ByteBuffer...)}
* by calling {@link EndPoint#flush(ByteBuffer...)} until all content is written.
* The abstract method {@link #onIncompleteFlushed()} is called when not all content has been
* written after a call to flush and should organise for the {@link #completeWrite()}
* method to be called when a subsequent call to flush should be able to make more progress.
*
* TODO remove synchronisation
* A Utility class to help implement {@link EndPoint#write(Object, Callback, ByteBuffer...)} by calling
* {@link EndPoint#flush(ByteBuffer...)} until all content is written.
* The abstract method {@link #onIncompleteFlushed()} is called when not all content has been written after a call to
* flush and should organise for the {@link #completeWrite()} method to be called when a subsequent call to flush
* should be able to make more progress.
* <p>
*/
abstract public class WriteFlusher
{
private final static ByteBuffer[] NO_BUFFERS= new ByteBuffer[0];
private final AtomicBoolean _writing = new AtomicBoolean(false);
private final EndPoint _endp;
private static final Logger LOG = Log.getLogger(WriteFlusher.class);
private static final EnumMap<StateType, Set<StateType>> __stateTransitions = new EnumMap<>(StateType.class);
private static final State __IDLE = new IdleState();
private static final State __WRITING = new WritingState();
private static final State __COMPLETING = new CompletingState();
private final EndPoint _endPoint;
private final AtomicReference<State> _state = new AtomicReference<>();
private ByteBuffer[] _buffers;
private Object _context;
private Callback<Object> _callback;
protected WriteFlusher(EndPoint endp)
static
{
_endp=endp;
// fill the state machine
__stateTransitions.put(StateType.IDLE, EnumSet.of(StateType.WRITING));
__stateTransitions.put(StateType.WRITING, EnumSet.of(StateType.IDLE, StateType.PENDING, StateType.FAILED));
__stateTransitions.put(StateType.PENDING, EnumSet.of(StateType.COMPLETING,StateType.IDLE));
__stateTransitions.put(StateType.COMPLETING, EnumSet.of(StateType.IDLE, StateType.PENDING, StateType.FAILED));
__stateTransitions.put(StateType.FAILED, EnumSet.of(StateType.IDLE));
}
/* ------------------------------------------------------------ */
public synchronized <C> void write(C context, Callback<C> callback, ByteBuffer... buffers)
// A write operation may either complete immediately:
// IDLE-->WRITING-->IDLE
// Or it may not completely flush and go via the PENDING state
// IDLE-->WRITING-->PENDING-->COMPLETING-->IDLE
// Or it may take several cycles to complete
// IDLE-->WRITING-->PENDING-->COMPLETING-->PENDING-->COMPLETING-->IDLE
//
// If a failure happens while in IDLE, it is a noop since there is no operation to tell of the failure.
// If a failure happens in PENDING state, then the fail method calls the pending callback and moves to IDLE state
// Otherwise if a fail happens, the state is set to FAIL, so that a subsequent attempt to move out of WRITING or COMPLETING
// will discover the failure and call the callbacks before returning to IDLE
// Thus the possible paths for a failure are:
//
// IDLE--(fail)-->IDLE
// IDLE-->WRITING--(fail)-->FAILED-->IDLE
// IDLE-->WRITING-->PENDING--(fail)-->IDLE
// IDLE-->WRITING-->PENDING-->COMPLETING--(fail)-->FAILED-->IDLE
//
// So a call to fail in the PENDING state will be directly handled and the state changed to IDLE
// A call to fail in the WRITING or COMPLETING states will just set the state to FAILED and the failure will be
// handled with the write or completeWrite methods try to move the state from what they thought it was.
//
protected WriteFlusher(EndPoint endPoint)
{
if (callback==null)
throw new IllegalArgumentException();
if (!_writing.compareAndSet(false,true))
_state.set(__IDLE);
_endPoint = endPoint;
}
private enum StateType
{
IDLE,
WRITING,
PENDING,
COMPLETING,
FAILED
}
/**
* Tries to update the current state to the given new state.
* @param nextState the desired new state
* @return the previous state or null if the state transition failed
* @throws WritePendingException if currentState is WRITING and new state is WRITING (api usage error)
*/
private boolean updateState(State previous,State next)
{
if (!isTransitionAllowed(previous,next))
throw new IllegalStateException();
return _state.compareAndSet(previous,next);
}
private void fail(PendingState<?> pending)
{
State current = _state.get();
if (current.getType()==StateType.FAILED)
{
FailedState failed=(FailedState)current;
if (updateState(failed,__IDLE))
{
pending.fail(failed.getCause());
return;
}
}
throw new IllegalStateException();
}
private void ignoreFail()
{
State current = _state.get();
while (current.getType()==StateType.FAILED)
{
if (updateState(current,__IDLE))
return;
current = _state.get();
}
}
private boolean isTransitionAllowed(State currentState, State newState)
{
Set<StateType> allowedNewStateTypes = __stateTransitions.get(currentState.getType());
if (currentState.getType() == StateType.WRITING && newState.getType() == StateType.WRITING)
{
throw new WritePendingException();
}
if (!allowedNewStateTypes.contains(newState.getType()))
{
LOG.debug("StateType update: {} -> {} not allowed", currentState, newState);
return false;
}
return true;
}
/**
* State represents a State of WriteFlusher.
*/
private static class State
{
private final StateType _type;
private State(StateType stateType)
{
_type = stateType;
}
public StateType getType()
{
return _type;
}
@Override
public String toString()
{
return String.format("%s", _type);
}
}
/**
* In IdleState WriteFlusher is idle and accepts new writes
*/
private static class IdleState extends State
{
private IdleState()
{
super(StateType.IDLE);
}
}
/**
* In WritingState WriteFlusher is currently writing.
*/
private static class WritingState extends State
{
private WritingState()
{
super(StateType.WRITING);
}
}
/**
* In FailedState no more operations are allowed. The current implementation will never recover from this state.
*/
private static class FailedState extends State
{
private final Throwable _cause;
private FailedState(Throwable cause)
{
super(StateType.FAILED);
_cause=cause;
}
public Throwable getCause()
{
return _cause;
}
}
/**
* In CompletingState WriteFlusher is flushing buffers that have not been fully written in write(). If write()
* didn't flush all buffers in one go, it'll switch the State to PendingState. completeWrite() will then switch to
* this state and try to flush the remaining buffers.
*/
private static class CompletingState extends State
{
private CompletingState()
{
super(StateType.COMPLETING);
}
}
/**
* In PendingState not all buffers could be written in one go. Then write() will switch to PendingState() and
* preserve the state by creating a new PendingState object with the given parameters.
*
* @param <C>
*/
private class PendingState<C> extends State
{
private final C _context;
private final Callback<C> _callback;
private ByteBuffer[] _buffers;
private PendingState(ByteBuffer[] buffers, C context, Callback<C> callback)
{
super(StateType.PENDING);
_buffers = buffers;
_context = context;
_callback = callback;
}
public ByteBuffer[] getBuffers()
{
return _buffers;
}
protected void fail(Throwable cause)
{
_callback.failed(_context, cause);
}
protected void complete()
{
_callback.completed(_context);
}
}
/**
* Abstract call to be implemented by specific WriteFlushers. It should schedule a call to {@link #completeWrite()}
* or {@link #onFail(Throwable)} when appropriate.
*/
abstract protected void onIncompleteFlushed();
/**
* Tries to switch state to WRITING. If successful it writes the given buffers to the EndPoint. If state transition
* fails it'll fail the callback.
*
* If not all buffers can be written in one go it creates a new {@link PendingState} object to preserve the state
* and then calls {@link #onIncompleteFlushed()}. The remaining buffers will be written in {@link #completeWrite()}.
*
* If all buffers have been written it calls callback.complete().
*
* @param context context to pass to the callback
* @param callback the callback to call on either failed or complete
* @param buffers the buffers to flush to the endpoint
* @param <C> type of the context
*/
public <C> void write(C context, Callback<C> callback, ByteBuffer... buffers) throws WritePendingException
{
if (callback == null)
throw new IllegalArgumentException();
LOG.debug("write: {}", this);
if (!updateState(__IDLE,__WRITING))
throw new WritePendingException();
try
{
_endp.flush(buffers);
_endPoint.flush(buffers);
// Are we complete?
for (ByteBuffer b : buffers)
{
if (b.hasRemaining())
{
_buffers=buffers;
_context=context;
_callback=(Callback<Object>)callback;
_writing.set(true); // Needed as memory barrier
onIncompleteFlushed();
PendingState<?> pending=new PendingState<>(buffers, context, callback);
if (updateState(__WRITING,pending))
onIncompleteFlushed();
else
fail(new PendingState<>(buffers, context, callback));
return;
}
}
// If updateState didn't succeed, we don't care as our buffers have been written
if (!updateState(__WRITING,__IDLE))
ignoreFail();
callback.completed(context);
}
catch (IOException e)
{
if (updateState(__WRITING,__IDLE))
callback.failed(context, e);
else
fail(new PendingState<>(buffers, context, callback));
}
}
/**
* Complete a write that has not completed and that called {@link #onIncompleteFlushed()} to request a call to this
* method when a call to {@link EndPoint#flush(ByteBuffer...)} is likely to be able to progress.
*
* It tries to switch from PENDING to COMPLETING. If state transition fails, then it does nothing as the callback
* should have been already failed. That's because the only way to switch from PENDING outside this method is
* {@link #onFail(Throwable)} or {@link #onClose()}
*/
public void completeWrite()
{
State previous = _state.get();
PendingState<?> pending=null;
if (previous.getType()!=StateType.PENDING)
return; // failure already handled.
pending=(PendingState<?>)previous;
if (!updateState(pending,__COMPLETING))
return; // failure already handled.
try
{
ByteBuffer[] buffers = pending.getBuffers();
_endPoint.flush(buffers);
// Are we complete?
for (ByteBuffer b : buffers)
{
if (b.hasRemaining())
{
if (updateState(__COMPLETING,pending))
onIncompleteFlushed();
else
fail(pending);
return;
}
}
if (!_writing.compareAndSet(true,false))
throw new ConcurrentModificationException();
callback.completed(context);
// If updateState didn't succeed, we don't care as our buffers have been written
if (!updateState(__COMPLETING,__IDLE))
ignoreFail();
pending.complete();
}
catch (IOException e)
{
if (!_writing.compareAndSet(true,false))
throw new ConcurrentModificationException(e);
callback.failed(context,e);
if(updateState(__COMPLETING,__IDLE))
pending.fail(e);
else
fail(pending);
}
}
/* ------------------------------------------------------------ */
/**
* Abstract call to be implemented by specific WriteFlushers.
* It should schedule a call to {@link #completeWrite()} or
* {@link #failed(Throwable)} when appropriate.
* @return true if a flush can proceed.
*/
abstract protected void onIncompleteFlushed();
/* ------------------------------------------------------------ */
/* Remove empty buffers from the start of a multi buffer array
*/
private synchronized ByteBuffer[] compact(ByteBuffer[] buffers)
public void onFail(Throwable cause)
{
if (buffers.length<2)
return buffers;
int b=0;
while (b<buffers.length && BufferUtil.isEmpty(buffers[b]))
b++;
if (b==0)
return buffers;
if (b==buffers.length)
return NO_BUFFERS;
ByteBuffer[] compact=new ByteBuffer[buffers.length-b];
System.arraycopy(buffers,b,compact,0,compact.length);
return compact;
}
/* ------------------------------------------------------------ */
/**
* Complete a write that has not completed and that called
* {@link #onIncompleteFlushed()} to request a call to this
* method when a call to {@link EndPoint#flush(ByteBuffer...)}
* is likely to be able to progress.
*/
public synchronized void completeWrite()
{
if (!isWriting())
return; // TODO throw?
try
LOG.debug("failed: " + this, cause);
// Keep trying to handle the failure until we get to IDLE or FAILED state
while(true)
{
while(true)
State current=_state.get();
switch(current.getType())
{
_buffers=compact(_buffers);
_endp.flush(_buffers);
// Are we complete?
for (ByteBuffer b : _buffers)
{
if (b.hasRemaining())
case IDLE:
return;
case PENDING:
PendingState<?> pending = (PendingState<?>)current;
if (updateState(pending,__IDLE))
{
onIncompleteFlushed();
pending.fail(cause);
return;
}
}
break;
break;
default:
if (updateState(current,new FailedState(cause)))
return;
break;
}
// we are complete and ready
Callback<Object> callback=_callback;
Object context=_context;
_buffers=null;
_callback=null;
_context=null;
if (!_writing.compareAndSet(true,false))
throw new ConcurrentModificationException();
callback.completed(context);
}
catch (IOException e)
}
public void onClose()
{
if (_state.get()==__IDLE)
return;
onFail(new ClosedChannelException());
}
public boolean isIdle()
{
return _state.get().getType() == StateType.IDLE;
}
public boolean isInProgress()
{
switch(_state.get().getType())
{
Callback<Object> callback=_callback;
Object context=_context;
_buffers=null;
_callback=null;
_context=null;
if (!_writing.compareAndSet(true,false))
throw new ConcurrentModificationException();
callback.failed(context,e);
case WRITING:
case PENDING:
case COMPLETING:
return true;
default:
return false;
}
return;
}
/* ------------------------------------------------------------ */
/**
* Fail the write in progress and cause any calls to get to throw
* the cause wrapped as an execution exception.
* @return true if a write was in progress
*/
public synchronized boolean failed(Throwable cause)
{
if (!_writing.compareAndSet(true,false))
return false;
Callback<Object> callback=_callback;
Object context=_context;
_buffers=null;
_callback=null;
_context=null;
callback.failed(context,cause);
return true;
}
/* ------------------------------------------------------------ */
/**
* Fail the write with a {@link ClosedChannelException}. This is similar
* to a call to {@link #failed(Throwable)}, except that the exception is
* not instantiated unless a write was in progress.
* @return true if a write was in progress
*/
public synchronized boolean close()
{
if (!_writing.compareAndSet(true,false))
return false;
Callback<Object> callback=_callback;
Object context=_context;
_buffers=null;
_callback=null;
_context=null;
callback.failed(context,new ClosedChannelException());
return true;
}
/* ------------------------------------------------------------ */
public synchronized boolean isWriting()
{
return _writing.get();
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return String.format("WriteFlusher@%x{%b,%s,%s}",hashCode(),isWriting(),_callback,_context);
return String.format("WriteFlusher@%x{%s}", hashCode(), _state.get());
}
}

View File

@ -17,20 +17,20 @@ import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.Arrays;
import java.util.concurrent.Executor;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status;
import javax.net.ssl.SSLException;
import org.eclipse.jetty.io.AbstractAsyncConnection;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AbstractEndPoint;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.ReadInterest;
import org.eclipse.jetty.io.FillInterest;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.SelectChannelEndPoint;
import org.eclipse.jetty.io.WriteFlusher;
@ -40,27 +40,27 @@ import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* An AsyncConnection that acts as an intercepter between an AsyncEndPoint providing SSL encrypted data
* and another consumer of an AsyncEndPoint (typically an {@link AsyncConnection} like HttpConnection) that
* A Connection that acts as an intercepter between an EndPoint providing SSL encrypted data
* and another consumer of an EndPoint (typically an {@link Connection} like HttpConnection) that
* wants unencrypted data.
* <p>
* The connector uses an {@link AsyncEndPoint} (typically {@link SelectChannelEndPoint}) as
* it's source/sink of encrypted data. It then provides an endpoint via {@link #getSslEndPoint()} to
* The connector uses an {@link EndPoint} (typically {@link SelectChannelEndPoint}) as
* it's source/sink of encrypted data. It then provides an endpoint via {@link #getDecryptedEndPoint()} to
* expose a source/sink of unencrypted data to another connection (eg HttpConnection).
* <p>
* The design of this class is based on a clear separation between the passive methods, which do not block nor schedule any
* asynchronous callbacks, and active methods that do schedule asynchronous callbacks.
* <p>
* The passive methods are {@link DecryptedEndPoint#fill(ByteBuffer)} and {@link DecryptedEndPoint#flush(ByteBuffer...)}. They make best
* effort attempts to progress the connection using only calls to the encrypted {@link AsyncEndPoint#fill(ByteBuffer)} and {@link AsyncEndPoint#flush(ByteBuffer...)}
* effort attempts to progress the connection using only calls to the encrypted {@link EndPoint#fill(ByteBuffer)} and {@link EndPoint#flush(ByteBuffer...)}
* methods. They will never block nor schedule any readInterest or write callbacks. If a fill/flush cannot progress either because
* of network congestion or waiting for an SSL handshake message, then the fill/flush will simply return with zero bytes filled/flushed.
* Specifically, if a flush cannot proceed because it needs to receive a handshake message, then the flush will attempt to fill bytes from the
* encrypted endpoint, but if insufficient bytes are read it will NOT call {@link AsyncEndPoint#fillInterested(Object, Callback)}.
* encrypted endpoint, but if insufficient bytes are read it will NOT call {@link EndPoint#fillInterested(Object, Callback)}.
* <p>
* It is only the active methods : {@link DecryptedEndPoint#fillInterested(Object, Callback)} and
* {@link DecryptedEndPoint#write(Object, Callback, ByteBuffer...)} that may schedule callbacks by calling the encrypted
* {@link AsyncEndPoint#fillInterested(Object, Callback)} and {@link AsyncEndPoint#write(Object, Callback, ByteBuffer...)}
* {@link EndPoint#fillInterested(Object, Callback)} and {@link EndPoint#write(Object, Callback, ByteBuffer...)}
* methods. For normal data handling, the decrypted fillInterest method will result in an encrypted fillInterest and a decrypted
* write will result in an encrypted write. However, due to SSL handshaking requirements, it is also possible for a decrypted fill
* to call the encrypted write and for the decrypted flush to call the encrypted fillInterested methods.
@ -70,7 +70,7 @@ import org.eclipse.jetty.util.log.Logger;
* be called again and make another best effort attempt to progress the connection.
*
*/
public class SslConnection extends AbstractAsyncConnection
public class SslConnection extends AbstractConnection
{
private static final Logger LOG = Log.getLogger(SslConnection.class);
private final ByteBufferPool _bufferPool;
@ -82,7 +82,7 @@ public class SslConnection extends AbstractAsyncConnection
private final boolean _encryptedDirectBuffers = false;
private final boolean _decryptedDirectBuffers = false;
public SslConnection(ByteBufferPool byteBufferPool, Executor executor, AsyncEndPoint endPoint, SSLEngine sslEngine)
public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine)
{
super(endPoint, executor, true);
this._bufferPool = byteBufferPool;
@ -95,7 +95,7 @@ public class SslConnection extends AbstractAsyncConnection
return _sslEngine;
}
public AsyncEndPoint getSslEndPoint()
public EndPoint getDecryptedEndPoint()
{
return _decryptedEndPoint;
}
@ -112,6 +112,8 @@ public class SslConnection extends AbstractAsyncConnection
if (_sslEngine.getUseClientMode())
_decryptedEndPoint.write(null, new Callback.Empty<>(), BufferUtil.EMPTY_BUFFER);
getDecryptedEndPoint().getConnection().onOpen();
}
catch (SSLException x)
{
@ -136,14 +138,13 @@ public class SslConnection extends AbstractAsyncConnection
{
// wake up whoever is doing the fill or the flush so they can
// do all the filling, unwrapping ,wrapping and flushing
if (_decryptedEndPoint._readInterest.isInterested())
_decryptedEndPoint._readInterest.readable();
_decryptedEndPoint.getFillInterest().fillable();
// If we are handshaking, then wake up any waiting write as well as it may have been blocked on the read
if ( _decryptedEndPoint._flushRequiresFillToProgress)
{
_decryptedEndPoint._flushRequiresFillToProgress = false;
_decryptedEndPoint._writeFlusher.completeWrite();
_decryptedEndPoint.getWriteFlusher().completeWrite();
}
}
}
@ -162,13 +163,12 @@ public class SslConnection extends AbstractAsyncConnection
synchronized(_decryptedEndPoint)
{
if (_decryptedEndPoint._readInterest.isInterested())
_decryptedEndPoint._readInterest.failed(cause);
_decryptedEndPoint.getFillInterest().onFail(cause);
if (_decryptedEndPoint._flushRequiresFillToProgress)
{
_decryptedEndPoint._flushRequiresFillToProgress = false;
_decryptedEndPoint._writeFlusher.failed(cause);
_decryptedEndPoint.getWriteFlusher().onFail(cause);
}
}
}
@ -177,33 +177,20 @@ public class SslConnection extends AbstractAsyncConnection
@Override
public String toString()
{
return String.format("SslConnection@%x{%s,%s%s}",
return String.format("%s{%s}",
hashCode(),
_sslEngine.getHandshakeStatus(),
_decryptedEndPoint._readInterest.isInterested() ? "R" : "",
_decryptedEndPoint._writeFlusher.isWriting() ? "W" : "");
_sslEngine.getHandshakeStatus());
}
/* ------------------------------------------------------------ */
public class DecryptedEndPoint extends AbstractEndPoint implements AsyncEndPoint
public class DecryptedEndPoint extends AbstractEndPoint
{
private AsyncConnection _connection;
private boolean _fillRequiresFlushToProgress;
private boolean _flushRequiresFillToProgress;
private boolean _cannotAcceptMoreAppDataToFlush;
private boolean _needToFillMoreDataToProgress;
private boolean _ishut = false;
@Override
public void onOpen()
{
}
@Override
public void onClose()
{
}
private final Callback<Void> _writeCallback = new Callback<Void>()
{
@ -224,11 +211,10 @@ public class SslConnection extends AbstractAsyncConnection
if (_fillRequiresFlushToProgress)
{
_fillRequiresFlushToProgress = false;
_readInterest.readable();
getFillInterest().fillable();
}
if (_writeFlusher.isWriting())
_writeFlusher.completeWrite();
getWriteFlusher().completeWrite();
}
}
@ -250,105 +236,112 @@ public class SslConnection extends AbstractAsyncConnection
if (_fillRequiresFlushToProgress)
{
_fillRequiresFlushToProgress = false;
_readInterest.failed(x);
getFillInterest().onFail(x);
}
if (_writeFlusher.isWriting())
_writeFlusher.failed(x);
getWriteFlusher().onFail(x);
// TODO release all buffers??? or may in onClose
}
}
};
private final ReadInterest _readInterest = new ReadInterest()
{
@Override
protected boolean needsFill() throws IOException
{
// This means that the decrypted data consumer has called the fillInterested
// method on the DecryptedEndPoint, so we have to work out if there is
// decrypted data to be filled or what callbacks to setup to be told when there
// might be more encrypted data available to attempt another call to fill
synchronized (DecryptedEndPoint.this)
{
// Do we already have some app data, then app can fill now so return true
if (BufferUtil.hasContent(_decryptedInput))
return true;
// If we have no encrypted data to decrypt OR we have some, but it is not enough
if (BufferUtil.isEmpty(_encryptedInput) || _needToFillMoreDataToProgress)
{
// We are not ready to read data
// Are we actually write blocked?
if (_fillRequiresFlushToProgress)
{
// we must be blocked trying to write before we can read
// Do we have data to write
if (BufferUtil.hasContent(_encryptedOutput))
{
// write it
_cannotAcceptMoreAppDataToFlush = true;
getEndPoint().write(null, _writeCallback, _encryptedOutput);
}
else
{
// we have already written the net data
// pretend we are readable so the wrap is done by next readable callback
_fillRequiresFlushToProgress = false;
return true;
}
}
else
// Normal readable callback
// Get called back on onfillable when then is more data to fill
SslConnection.this.fillInterested();
return false;
}
else
{
// We are ready to read data
return true;
}
}
}
};
private final WriteFlusher _writeFlusher = new WriteFlusher(this)
{
@Override
protected void onIncompleteFlushed()
{
// This means that the decripted endpoint write method was called and not
// all data could be wrapped. So either we need to write some encrypted data,
// OR if we are handshaking we need to read some encrypted data OR
// if neither than we should just try the flush again.
synchronized (DecryptedEndPoint.this)
{
// If we have pending output data,
if (BufferUtil.hasContent(_encryptedOutput))
{
// write it
_cannotAcceptMoreAppDataToFlush = true;
getEndPoint().write(null, _writeCallback, _encryptedOutput);
}
else if (_sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP)
// we are actually read blocked in order to write
SslConnection.this.fillInterested();
else
// try the flush again
completeWrite();
}
}
};
public DecryptedEndPoint()
{
super(getEndPoint().getLocalAddress(), getEndPoint().getRemoteAddress());
// TODO does this need idle timeouts
super(null,getEndPoint().getLocalAddress(), getEndPoint().getRemoteAddress());
}
@Override
protected FillInterest getFillInterest()
{
return super.getFillInterest();
}
@Override
protected WriteFlusher getWriteFlusher()
{
return super.getWriteFlusher();
}
@Override
protected void onIncompleteFlush()
{
// This means that the decripted endpoint write method was called and not
// all data could be wrapped. So either we need to write some encrypted data,
// OR if we are handshaking we need to read some encrypted data OR
// if neither than we should just try the flush again.
synchronized (DecryptedEndPoint.this)
{
// If we have pending output data,
if (BufferUtil.hasContent(_encryptedOutput))
{
// write it
_cannotAcceptMoreAppDataToFlush = true;
getEndPoint().write(null, _writeCallback, _encryptedOutput);
}
else if (_sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_UNWRAP)
// we are actually read blocked in order to write
SslConnection.this.fillInterested();
else
// try the flush again
getWriteFlusher().completeWrite();
}
}
@Override
protected boolean needsFill() throws IOException
{
// This means that the decrypted data consumer has called the fillInterested
// method on the DecryptedEndPoint, so we have to work out if there is
// decrypted data to be filled or what callbacks to setup to be told when there
// might be more encrypted data available to attempt another call to fill
synchronized (DecryptedEndPoint.this)
{
// Do we already have some app data, then app can fill now so return true
if (BufferUtil.hasContent(_decryptedInput))
return true;
// If we have no encrypted data to decrypt OR we have some, but it is not enough
if (BufferUtil.isEmpty(_encryptedInput) || _needToFillMoreDataToProgress)
{
// We are not ready to read data
// Are we actually write blocked?
if (_fillRequiresFlushToProgress)
{
// we must be blocked trying to write before we can read
// Do we have data to write
if (BufferUtil.hasContent(_encryptedOutput))
{
// write it
_cannotAcceptMoreAppDataToFlush = true;
getEndPoint().write(null, _writeCallback, _encryptedOutput);
}
else
{
// we have already written the net data
// pretend we are readable so the wrap is done by next readable callback
_fillRequiresFlushToProgress = false;
return true;
}
}
else
// Normal readable callback
// Get called back on onfillable when then is more data to fill
SslConnection.this.fillInterested();
return false;
}
else
{
// We are ready to read data
return true;
}
}
}
public SslConnection getSslConnection()
@ -356,18 +349,6 @@ public class SslConnection extends AbstractAsyncConnection
return SslConnection.this;
}
@Override
public <C> void fillInterested(C context, Callback<C> callback) throws IllegalStateException
{
_readInterest.register(context, callback);
}
@Override
public <C> void write(C context, Callback<C> callback, ByteBuffer... buffers) throws IllegalStateException
{
_writeFlusher.write(context, callback, buffers);
}
@Override
public synchronized int fill(ByteBuffer buffer) throws IOException
{
@ -551,7 +532,7 @@ public class SslConnection extends AbstractAsyncConnection
// or busy handshaking, then zero bytes may be taken from appOuts and this method
// will return 0 (even if some handshake bytes were flushed and filled).
// it is the applications responsibility to call flush again - either in a busy loop
// or better yet by using AsyncEndPoint#write to do the flushing.
// or better yet by using EndPoint#write to do the flushing.
LOG.debug("{} flush enter {}", SslConnection.this, Arrays.toString(appOuts));
try
@ -628,7 +609,7 @@ public class SslConnection extends AbstractAsyncConnection
case NEED_UNWRAP:
// Ah we need to fill some data so we can write.
// So if we were not called from fill and the app is not reading anyway
if (!_fillRequiresFlushToProgress && !_readInterest.isInterested())
if (!_fillRequiresFlushToProgress && !getFillInterest().isInterested())
{
// Tell the onFillable method that there might be a write to complete
// TODO move this to the writeFlusher?
@ -711,24 +692,5 @@ public class SslConnection extends AbstractAsyncConnection
{
return _ishut;
}
@Override
public AsyncConnection getAsyncConnection()
{
return _connection;
}
@Override
public void setAsyncConnection(AsyncConnection connection)
{
_connection = connection;
}
@Override
public String toString()
{
return String.format("%s{%s%s%s}", super.toString(), _readInterest.isInterested() ? "R" : "", _writeFlusher.isWriting() ? "W" : "", _cannotAcceptMoreAppDataToFlush ? "w" : "");
}
}
}

View File

@ -1,192 +0,0 @@
package org.eclipse.jetty.io;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.FutureCallback;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class AsyncByteArrayEndPointTest
{
private ScheduledExecutorService _scheduler;
@Before
public void before()
{
_scheduler = Executors.newSingleThreadScheduledExecutor();
}
@After
public void after()
{
_scheduler.shutdownNow();
}
@Test
public void testReadable() throws Exception
{
AsyncByteArrayEndPoint endp = new AsyncByteArrayEndPoint(_scheduler, 5000);
endp.setInput("test input");
ByteBuffer buffer = BufferUtil.allocate(1024);
FutureCallback<String> fcb = new FutureCallback<>();
endp.fillInterested("CTX", fcb);
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals(10, endp.fill(buffer));
assertEquals("test input", BufferUtil.toString(buffer));
fcb = new FutureCallback<>();
endp.fillInterested("CTX", fcb);
assertFalse(fcb.isDone());
assertEquals(0, endp.fill(buffer));
endp.setInput(" more");
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals(5, endp.fill(buffer));
assertEquals("test input more", BufferUtil.toString(buffer));
fcb = new FutureCallback<>();
endp.fillInterested("CTX", fcb);
assertFalse(fcb.isDone());
assertEquals(0, endp.fill(buffer));
endp.setInput((ByteBuffer)null);
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals(-1, endp.fill(buffer));
fcb = new FutureCallback<>();
endp.fillInterested("CTX", fcb);
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals(-1, endp.fill(buffer));
endp.close();
fcb = new FutureCallback<>();
endp.fillInterested("CTX", fcb);
assertTrue(fcb.isDone());
try
{
fcb.get();
fail();
}
catch (ExecutionException e)
{
assertThat(e.toString(), containsString("Closed"));
}
}
@Test
public void testWrite() throws Exception
{
AsyncByteArrayEndPoint endp = new AsyncByteArrayEndPoint(_scheduler, 5000, (byte[])null, 15);
endp.setGrowOutput(false);
endp.setOutput(BufferUtil.allocate(10));
ByteBuffer data = BufferUtil.toBuffer("Data.");
ByteBuffer more = BufferUtil.toBuffer(" Some more.");
FutureCallback<String> fcb = new FutureCallback<>();
endp.write("CTX", fcb, data);
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals("Data.", endp.getOutputString());
fcb = new FutureCallback<>();
endp.write("CTX", fcb, more);
assertFalse(fcb.isDone());
assertEquals("Data. Some", endp.getOutputString());
assertEquals("Data. Some", endp.takeOutputString());
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals(" more.", endp.getOutputString());
}
@Test
public void testIdle() throws Exception
{
AsyncByteArrayEndPoint endp = new AsyncByteArrayEndPoint(_scheduler, 500);
endp.setInput("test");
endp.setGrowOutput(false);
endp.setOutput(BufferUtil.allocate(5));
// no idle check
assertTrue(endp.isOpen());
Thread.sleep(1000);
assertTrue(endp.isOpen());
// normal read
ByteBuffer buffer = BufferUtil.allocate(1024);
FutureCallback<Void> fcb = new FutureCallback<>();
endp.fillInterested(null, fcb);
assertTrue(fcb.isDone());
assertEquals(null, fcb.get());
assertEquals(4, endp.fill(buffer));
assertEquals("test", BufferUtil.toString(buffer));
// read timeout
fcb = new FutureCallback<>();
endp.fillInterested(null, fcb);
long start = System.currentTimeMillis();
try
{
fcb.get();
fail();
}
catch (ExecutionException t)
{
assertThat(t.getCause(), Matchers.instanceOf(TimeoutException.class));
}
assertThat(System.currentTimeMillis() - start, Matchers.greaterThan(100L));
assertTrue(endp.isOpen());
// write timeout
fcb = new FutureCallback<>();
start = System.currentTimeMillis();
endp.write(null, fcb, BufferUtil.toBuffer("This is too long"));
try
{
fcb.get();
fail();
}
catch (ExecutionException t)
{
assertThat(t.getCause(), Matchers.instanceOf(TimeoutException.class));
}
assertThat(System.currentTimeMillis() - start, Matchers.greaterThan(100L));
assertTrue(endp.isOpen());
// Still no idle close
Thread.sleep(1000);
assertTrue(endp.isOpen());
// shutdown out
endp.shutdownOutput();
// idle close
Thread.sleep(1000);
assertFalse(endp.isOpen());
}
}

View File

@ -2,17 +2,41 @@ package org.eclipse.jetty.io;
import static junit.framework.Assert.assertEquals;
import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeoutException;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.FutureCallback;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
public class ByteArrayEndPointTest
{
private ScheduledExecutorService _scheduler;
@Before
public void before()
{
_scheduler = Executors.newSingleThreadScheduledExecutor();
}
@After
public void after()
{
_scheduler.shutdownNow();
}
@Test
public void testFill() throws Exception
{
@ -104,6 +128,159 @@ public class ByteArrayEndPointTest
assertEquals("data.",BufferUtil.toString(endp.takeOutput()));
}
@Test
public void testReadable() throws Exception
{
ByteArrayEndPoint endp = new ByteArrayEndPoint(_scheduler, 5000);
endp.setInput("test input");
ByteBuffer buffer = BufferUtil.allocate(1024);
FutureCallback<String> fcb = new FutureCallback<>();
endp.fillInterested("CTX", fcb);
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals(10, endp.fill(buffer));
assertEquals("test input", BufferUtil.toString(buffer));
fcb = new FutureCallback<>();
endp.fillInterested("CTX", fcb);
assertFalse(fcb.isDone());
assertEquals(0, endp.fill(buffer));
endp.setInput(" more");
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals(5, endp.fill(buffer));
assertEquals("test input more", BufferUtil.toString(buffer));
fcb = new FutureCallback<>();
endp.fillInterested("CTX", fcb);
assertFalse(fcb.isDone());
assertEquals(0, endp.fill(buffer));
endp.setInput((ByteBuffer)null);
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals(-1, endp.fill(buffer));
fcb = new FutureCallback<>();
endp.fillInterested("CTX", fcb);
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals(-1, endp.fill(buffer));
endp.close();
fcb = new FutureCallback<>();
endp.fillInterested("CTX", fcb);
assertTrue(fcb.isDone());
try
{
fcb.get();
fail();
}
catch (ExecutionException e)
{
assertThat(e.toString(), containsString("Closed"));
}
}
@Test
public void testWrite() throws Exception
{
ByteArrayEndPoint endp = new ByteArrayEndPoint(_scheduler, 5000, (byte[])null, 15);
endp.setGrowOutput(false);
endp.setOutput(BufferUtil.allocate(10));
ByteBuffer data = BufferUtil.toBuffer("Data.");
ByteBuffer more = BufferUtil.toBuffer(" Some more.");
FutureCallback<String> fcb = new FutureCallback<>();
endp.write("CTX", fcb, data);
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals("Data.", endp.getOutputString());
fcb = new FutureCallback<>();
endp.write("CTX", fcb, more);
assertFalse(fcb.isDone());
assertEquals("Data. Some", endp.getOutputString());
assertEquals("Data. Some", endp.takeOutputString());
assertTrue(fcb.isDone());
assertEquals("CTX", fcb.get());
assertEquals(" more.", endp.getOutputString());
}
@Test
public void testIdle() throws Exception
{
ByteArrayEndPoint endp = new ByteArrayEndPoint(_scheduler, 500);
endp.setInput("test");
endp.setGrowOutput(false);
endp.setOutput(BufferUtil.allocate(5));
// no idle check
assertTrue(endp.isOpen());
Thread.sleep(1000);
assertTrue(endp.isOpen());
// normal read
ByteBuffer buffer = BufferUtil.allocate(1024);
FutureCallback<Void> fcb = new FutureCallback<>();
endp.fillInterested(null, fcb);
assertTrue(fcb.isDone());
assertEquals(null, fcb.get());
assertEquals(4, endp.fill(buffer));
assertEquals("test", BufferUtil.toString(buffer));
// read timeout
fcb = new FutureCallback<>();
endp.fillInterested(null, fcb);
long start = System.currentTimeMillis();
try
{
fcb.get();
fail();
}
catch (ExecutionException t)
{
assertThat(t.getCause(), Matchers.instanceOf(TimeoutException.class));
}
assertThat(System.currentTimeMillis() - start, Matchers.greaterThan(100L));
assertTrue(endp.isOpen());
// write timeout
fcb = new FutureCallback<>();
start = System.currentTimeMillis();
endp.write(null, fcb, BufferUtil.toBuffer("This is too long"));
try
{
fcb.get();
fail();
}
catch (ExecutionException t)
{
assertThat(t.getCause(), Matchers.instanceOf(TimeoutException.class));
}
assertThat(System.currentTimeMillis() - start, Matchers.greaterThan(100L));
assertTrue(endp.isOpen());
// Still no idle close
Thread.sleep(1000);
assertTrue(endp.isOpen());
// shutdown out
endp.shutdownOutput();
// idle close
Thread.sleep(1000);
assertFalse(endp.isOpen());
}
}

View File

@ -41,8 +41,8 @@ public class ChannelEndPointTest extends EndPointTest<ChannelEndPoint>
{
EndPointPair<ChannelEndPoint> c = new EndPointPair<>();
c.client=new ChannelEndPoint(SocketChannel.open(connector.socket().getLocalSocketAddress()));
c.server=new ChannelEndPoint(connector.accept());
c.client=new ChannelEndPoint(null,SocketChannel.open(connector.socket().getLocalSocketAddress()));
c.server=new ChannelEndPoint(null,connector.accept());
return c;
}

View File

@ -62,7 +62,7 @@ public class SelectChannelEndPointInterestsTest
}
@Override
protected AsyncEndPoint newEndPoint(SocketChannel channel, ManagedSelector selector, SelectionKey selectionKey) throws IOException
protected EndPoint newEndPoint(SocketChannel channel, ManagedSelector selector, SelectionKey selectionKey) throws IOException
{
return new SelectChannelEndPoint(channel, selector, selectionKey, scheduler, 60000)
{
@ -76,10 +76,17 @@ public class SelectChannelEndPointInterestsTest
}
@Override
public AsyncConnection newConnection(SocketChannel channel, final AsyncEndPoint endPoint, Object attachment)
public Connection newConnection(SocketChannel channel, final EndPoint endPoint, Object attachment)
{
return new AbstractAsyncConnection(endPoint, threadPool)
return new AbstractConnection(endPoint, threadPool)
{
@Override
public void onOpen()
{
super.onOpen();
fillInterested();
}
@Override
public void onFillable()
{
@ -102,7 +109,7 @@ public class SelectChannelEndPointInterestsTest
init(new Interested()
{
@Override
public void onFillable(AsyncEndPoint endPoint, AbstractAsyncConnection connection)
public void onFillable(EndPoint endPoint, AbstractConnection connection)
{
ByteBuffer input = BufferUtil.allocate(2);
int read = fill(endPoint, input);
@ -136,7 +143,7 @@ public class SelectChannelEndPointInterestsTest
writeBlocked.set(true);
}
private int fill(AsyncEndPoint endPoint, ByteBuffer buffer)
private int fill(EndPoint endPoint, ByteBuffer buffer)
{
try
{
@ -184,7 +191,7 @@ public class SelectChannelEndPointInterestsTest
private interface Interested
{
void onFillable(AsyncEndPoint endPoint, AbstractAsyncConnection connection);
void onFillable(EndPoint endPoint, AbstractConnection connection);
void onIncompleteFlush();
}

View File

@ -1,5 +1,11 @@
package org.eclipse.jetty.io;
import static org.hamcrest.Matchers.greaterThan;
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.File;
import java.io.IOException;
import java.io.OutputStream;
@ -7,6 +13,7 @@ import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
@ -21,12 +28,6 @@ import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import static org.hamcrest.Matchers.greaterThan;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
{
@ -52,14 +53,14 @@ public class SelectChannelEndPointSslTest extends SelectChannelEndPointTest
}
@Override
protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint)
protected Connection newConnection(SocketChannel channel, EndPoint endpoint)
{
SSLEngine engine = __sslCtxFactory.newSslEngine();
engine.setUseClientMode(false);
SslConnection sslConnection = new SslConnection(__byteBufferPool, _threadPool, endpoint, engine);
AsyncConnection appConnection = super.newConnection(channel,sslConnection.getSslEndPoint());
sslConnection.getSslEndPoint().setAsyncConnection(appConnection);
Connection appConnection = super.newConnection(channel,sslConnection.getDecryptedEndPoint());
sslConnection.getDecryptedEndPoint().setConnection(appConnection);
_manager.connectionOpened(appConnection);
return sslConnection;

View File

@ -16,6 +16,12 @@
package org.eclipse.jetty.io;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
@ -42,16 +48,10 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.greaterThan;
import static org.hamcrest.Matchers.greaterThanOrEqualTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class SelectChannelEndPointTest
{
protected CountDownLatch _lastEndPointLatch;
protected volatile AsyncEndPoint _lastEndPoint;
protected volatile EndPoint _lastEndPoint;
protected ServerSocketChannel _connector;
protected QueuedThreadPool _threadPool = new QueuedThreadPool();
protected ScheduledExecutorService _scheduler = Executors.newSingleThreadScheduledExecutor();
@ -64,7 +64,7 @@ public class SelectChannelEndPointTest
}
@Override
public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment)
public Connection newConnection(SocketChannel channel, EndPoint endpoint, Object attachment)
{
return SelectChannelEndPointTest.this.newConnection(channel, endpoint);
}
@ -108,26 +108,33 @@ public class SelectChannelEndPointTest
return new Socket(_connector.socket().getInetAddress(), _connector.socket().getLocalPort());
}
protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint)
protected Connection newConnection(SocketChannel channel, EndPoint endpoint)
{
return new TestConnection(endpoint);
}
public class TestConnection extends AbstractAsyncConnection
public class TestConnection extends AbstractConnection
{
ByteBuffer _in = BufferUtil.allocate(32 * 1024);
ByteBuffer _out = BufferUtil.allocate(32 * 1024);
long _last = -1;
public TestConnection(AsyncEndPoint endp)
public TestConnection(EndPoint endp)
{
super(endp, _threadPool);
}
@Override
public void onOpen()
{
super.onOpen();
fillInterested();
}
@Override
public synchronized void onFillable()
{
AsyncEndPoint _endp = getEndPoint();
EndPoint _endp = getEndPoint();
try
{
_last = System.currentTimeMillis();
@ -462,12 +469,11 @@ public class SelectChannelEndPointTest
}
// But endpoint is still open.
assertTrue(_lastEndPoint.isOpen());
// Wait for another idle callback
Thread.sleep(idleTimeout * 2);
if(_lastEndPoint.isOpen())
// Wait for another idle callback
Thread.sleep(idleTimeout * 2);
// endpoint is closed.
assertFalse(_lastEndPoint.isOpen());
}
@ -540,7 +546,7 @@ public class SelectChannelEndPointTest
System.err.println("time=" + (now - start));
System.err.println("last=" + (now - last));
System.err.println("endp=" + _lastEndPoint);
System.err.println("conn=" + _lastEndPoint.getAsyncConnection());
System.err.println("conn=" + _lastEndPoint.getConnection());
e.printStackTrace();
}

View File

@ -13,10 +13,12 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSocket;
import junit.framework.Assert;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.BufferUtil;
@ -35,7 +37,7 @@ public class SslConnectionTest
private static SslContextFactory __sslCtxFactory=new SslContextFactory();
private static ByteBufferPool __byteBufferPool = new StandardByteBufferPool();
protected volatile AsyncEndPoint _lastEndp;
protected volatile EndPoint _lastEndp;
protected ServerSocketChannel _connector;
protected QueuedThreadPool _threadPool = new QueuedThreadPool();
protected ScheduledExecutorService _scheduler = Executors.newSingleThreadScheduledExecutor();
@ -48,14 +50,14 @@ public class SslConnectionTest
}
@Override
public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment)
public Connection newConnection(SocketChannel channel, EndPoint endpoint, Object attachment)
{
SSLEngine engine = __sslCtxFactory.newSslEngine();
engine.setUseClientMode(false);
SslConnection sslConnection = new SslConnection(__byteBufferPool, _threadPool, endpoint, engine);
AsyncConnection appConnection = new TestConnection(sslConnection.getSslEndPoint());
sslConnection.getSslEndPoint().setAsyncConnection(appConnection);
Connection appConnection = new TestConnection(sslConnection.getDecryptedEndPoint());
sslConnection.getDecryptedEndPoint().setConnection(appConnection);
connectionOpened(appConnection);
return sslConnection;
@ -103,24 +105,32 @@ public class SslConnectionTest
_connector.close();
}
public class TestConnection extends AbstractAsyncConnection
public class TestConnection extends AbstractConnection
{
ByteBuffer _in = BufferUtil.allocate(8*1024);
public TestConnection(AsyncEndPoint endp)
public TestConnection(EndPoint endp)
{
super(endp, _threadPool);
}
@Override
public void onOpen()
{
super.onOpen();
fillInterested();
}
@Override
public void onClose()
{
super.onClose();
}
@Override
public synchronized void onFillable()
{
AsyncEndPoint endp = getEndPoint();
EndPoint endp = getEndPoint();
try
{
boolean progress=true;

View File

@ -1,37 +1,62 @@
package org.eclipse.jetty.io;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.assertFalse;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.WritePendingException;
import java.security.SecureRandom;
import java.util.concurrent.Callable;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicBoolean;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback;
import org.eclipse.jetty.util.FutureCallback;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class WriteFlusherTest
{
ByteArrayEndPoint _endp;
final AtomicBoolean _flushIncomplete = new AtomicBoolean(false);
WriteFlusher _flusher;
final String _context = new String("Context");
@Mock
private EndPoint _endPointMock;
private WriteFlusher _flusher;
private final AtomicBoolean _flushIncomplete = new AtomicBoolean(false);
private final String _context = new String("Context");
private ByteArrayEndPoint _endp;
@Before
public void before()
{
_endp = new ByteArrayEndPoint(new byte[]{},10);
_flushIncomplete.set(false);
_flusher = new WriteFlusher(_endp)
{
{
@Override
protected void onIncompleteFlushed()
{
@ -39,35 +64,57 @@ public class WriteFlusherTest
}
};
}
@After
public void after()
@Test
public void testIgnorePreviousFailures() throws Exception
{
_endp.setGrowOutput(true);
FutureCallback<String> callback = new FutureCallback<>();
_flusher.onFail(new IOException("Ignored because no operation in progress"));
_flusher.write(_context,callback,BufferUtil.toBuffer("How "),BufferUtil.toBuffer("now "),BufferUtil.toBuffer("brown "),BufferUtil.toBuffer("cow!"));
assertCallbackIsDone(callback);
assertFlushIsComplete();
assertThat("context and callback.get() are equal", _context, equalTo(callback.get()));
assertThat("string in endpoint matches expected string", "How now brown cow!",
equalTo(_endp.takeOutputString()));
assertTrue(_flusher.isIdle());
}
@Test
public void testCompleteNoBlocking() throws Exception
{
_endp.setGrowOutput(true);
FutureCallback<String> callback = new FutureCallback<>();
_flusher.write(_context,callback,BufferUtil.toBuffer("How "),BufferUtil.toBuffer("now "),BufferUtil.toBuffer("brown "),BufferUtil.toBuffer("cow!"));
assertTrue(callback.isDone());
assertFalse(_flushIncomplete.get());
assertEquals(_context,callback.get());
assertEquals("How now brown cow!",_endp.takeOutputString());
assertCallbackIsDone(callback);
assertFlushIsComplete();
assertThat("context and callback.get() are equal", _context, equalTo(callback.get()));
assertThat("string in endpoint matches expected string", "How now brown cow!",
equalTo(_endp.takeOutputString()));
assertTrue(_flusher.isIdle());
}
private void assertFlushIsComplete()
{
assertThat("flush is complete", _flushIncomplete.get(), is(false));
}
private void assertCallbackIsDone(FutureCallback<String> callback)
{
assertThat("callback is done", callback.isDone(), is(true));
}
@Test
public void testClosedNoBlocking() throws Exception
{
_endp.close();
FutureCallback<String> callback = new FutureCallback<>();
_flusher.write(_context,callback,BufferUtil.toBuffer("How "),BufferUtil.toBuffer("now "),BufferUtil.toBuffer("brown "),BufferUtil.toBuffer("cow!"));
assertTrue(callback.isDone());
assertFalse(_flushIncomplete.get());
assertCallbackIsDone(callback);
assertFlushIsComplete();
try
{
assertEquals(_context,callback.get());
@ -80,17 +127,18 @@ public class WriteFlusherTest
Assert.assertThat(cause.getMessage(),Matchers.containsString("CLOSED"));
}
assertEquals("",_endp.takeOutputString());
assertTrue(_flusher.isIdle());
}
@Test
public void testCompleteBlocking() throws Exception
{
{
FutureCallback<String> callback = new FutureCallback<>();
_flusher.write(_context,callback,BufferUtil.toBuffer("How "),BufferUtil.toBuffer("now "),BufferUtil.toBuffer("brown "),BufferUtil.toBuffer("cow!"));
assertFalse(callback.isDone());
assertFalse(callback.isCancelled());
assertTrue(_flushIncomplete.get());
try
{
@ -104,12 +152,13 @@ public class WriteFlusherTest
assertEquals("How now br",_endp.takeOutputString());
_flusher.completeWrite();
assertTrue(callback.isDone());
assertCallbackIsDone(callback);
assertEquals(_context,callback.get());
assertEquals("own cow!",_endp.takeOutputString());
assertFalse(_flushIncomplete.get());
assertFlushIsComplete();
assertTrue(_flusher.isIdle());
}
@Test
public void testCloseWhileBlocking() throws Exception
{
@ -118,7 +167,7 @@ public class WriteFlusherTest
assertFalse(callback.isDone());
assertFalse(callback.isCancelled());
assertTrue(_flushIncomplete.get());
try
{
@ -133,8 +182,8 @@ public class WriteFlusherTest
assertEquals("How now br",_endp.takeOutputString());
_endp.close();
_flusher.completeWrite();
assertTrue(callback.isDone());
assertFalse(_flushIncomplete.get());
assertCallbackIsDone(callback);
assertFlushIsComplete();
try
{
assertEquals(_context,callback.get());
@ -147,6 +196,7 @@ public class WriteFlusherTest
Assert.assertThat(cause.getMessage(),Matchers.containsString("CLOSED"));
}
assertEquals("",_endp.takeOutputString());
assertTrue(_flusher.isIdle());
}
@Test
@ -157,7 +207,7 @@ public class WriteFlusherTest
assertFalse(callback.isDone());
assertFalse(callback.isCancelled());
assertTrue(_flushIncomplete.get());
try
{
@ -169,11 +219,11 @@ public class WriteFlusherTest
_flushIncomplete.set(false);
}
assertEquals("How now br",_endp.takeOutputString());
_flusher.failed(new IOException("Failure"));
assertEquals("How now br", _endp.takeOutputString());
_flusher.onFail(new IOException("Failure"));
_flusher.completeWrite();
assertTrue(callback.isDone());
assertFalse(_flushIncomplete.get());
assertCallbackIsDone(callback);
assertFlushIsComplete();
try
{
assertEquals(_context,callback.get());
@ -185,7 +235,332 @@ public class WriteFlusherTest
Assert.assertTrue(cause instanceof IOException);
Assert.assertThat(cause.getMessage(),Matchers.containsString("Failure"));
}
assertEquals("",_endp.takeOutputString());
assertEquals("", _endp.takeOutputString());
assertTrue(_flusher.isIdle());
}
private static class ConcurrentFlusher extends WriteFlusher implements Runnable
{
final ByteArrayEndPoint _endp;
final SecureRandom _random;
final ScheduledThreadPoolExecutor _scheduler;
final StringBuilder _content=new StringBuilder();
ConcurrentFlusher(ByteArrayEndPoint endp,SecureRandom random, ScheduledThreadPoolExecutor scheduler)
{
super(endp);
_endp=endp;
_random=random;
_scheduler=scheduler;
}
@Override
protected void onIncompleteFlushed()
{
_scheduler.schedule(this,1+_random.nextInt(9),TimeUnit.MILLISECONDS);
}
@Override
public synchronized void run()
{
_content.append(_endp.takeOutputString());
completeWrite();
}
@Override
public synchronized String toString()
{
_content.append(_endp.takeOutputString());
return _content.toString();
}
}
@Test
public void testConcurrent() throws Exception
{
final SecureRandom random = new SecureRandom();
final ScheduledThreadPoolExecutor scheduler = new ScheduledThreadPoolExecutor(100);
ConcurrentFlusher[] flushers = new ConcurrentFlusher[50000];
FutureCallback<?>[] futures = new FutureCallback<?>[flushers.length];
for (int i=0;i<flushers.length;i++)
{
int size=5+random.nextInt(15);
ByteArrayEndPoint endp = new ByteArrayEndPoint(new byte[]{},size);
final ConcurrentFlusher flusher = new ConcurrentFlusher(endp,random,scheduler);
flushers[i]=flusher;
final FutureCallback<String> callback = new FutureCallback<>();
futures[i]=callback;
scheduler.schedule(new Runnable()
{
@Override
public void run()
{
flusher.onFail(new Throwable("THE CAUSE"));
}
}
,random.nextInt(75)+1,TimeUnit.MILLISECONDS);
flusher.write(_context,callback,BufferUtil.toBuffer("How Now Brown Cow."),BufferUtil.toBuffer(" The quick brown fox jumped over the lazy dog!"));
}
int completed=0;
int failed=0;
for (int i=0;i<flushers.length;i++)
{
try
{
futures[i].get();
assertEquals("How Now Brown Cow. The quick brown fox jumped over the lazy dog!",flushers[i].toString());
completed++;
}
catch (Exception e)
{
assertThat(e.getMessage(),Matchers.containsString("THE CAUSE"));
failed++;
}
}
assertThat(completed,Matchers.greaterThan(0));
assertThat(failed,Matchers.greaterThan(0));
scheduler.shutdown();
}
@Test
@Ignore
public void testConcurrentAccessToWriteAndFailed() throws IOException, InterruptedException, ExecutionException
{
ExecutorService executor = Executors.newFixedThreadPool(16);
final CountDownLatch failedCalledLatch = new CountDownLatch(1);
final CountDownLatch writeCalledLatch = new CountDownLatch(1);
final CountDownLatch writeCompleteLatch = new CountDownLatch(1);
final WriteFlusher writeFlusher = new WriteFlusher(_endPointMock)
{
@Override
public <C> void write(C context, Callback<C> callback, ByteBuffer... buffers)
{
super.write(context, callback, buffers);
writeCompleteLatch.countDown();
}
@Override
protected void onIncompleteFlushed()
{
}
};
endPointFlushExpectation(writeCalledLatch, failedCalledLatch);
ExposingStateCallback callback = new ExposingStateCallback();
executor.submit(new Writer(writeFlusher, callback));
assertThat("Write has been called.", writeCalledLatch.await(5, TimeUnit.SECONDS), is(true));
executor.submit(new FailedCaller(writeFlusher, failedCalledLatch)).get();
// callback failed is NOT called because in WRITING state failed() doesn't know about the callback. However
// either the write succeeds or we get an IOException which will call callback.failed()
assertThat("callback failed", callback.isFailed(), is(false));
assertThat("write complete", writeCompleteLatch.await(5, TimeUnit.SECONDS), is(true));
// in this testcase we more or less emulate that the write has successfully finished and we return from
// EndPoint.flush() back to WriteFlusher.write(). Then someone calls failed. So the callback should have been
// completed.
assertThat("callback completed", callback.isCompleted(), is(true));
}
private class ExposingStateCallback extends FutureCallback
{
private boolean failed = false;
private boolean completed = false;
@Override
public void completed(Object context)
{
completed = true;
super.completed(context);
}
@Override
public void failed(Object context, Throwable cause)
{
failed = true;
super.failed(context, cause);
}
public boolean isFailed()
{
return failed;
}
public boolean isCompleted()
{
return completed;
}
}
@Ignore("Intermittent failures.") //TODO: fixme
@Test(expected = WritePendingException.class)
public void testConcurrentAccessToWrite() throws Throwable
{
ExecutorService executor = Executors.newFixedThreadPool(16);
final WriteFlusher writeFlusher = new WriteFlusher(_endPointMock)
{
@Override
protected void onIncompleteFlushed()
{
}
};
// in this test we just want to make sure that we called write twice at the same time
when(_endPointMock.flush(any(ByteBuffer[].class))).thenAnswer(new Answer<Object>()
{
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
// make sure we stay here, so write is called twice at the same time
Thread.sleep(5000);
return null;
}
});
executor.submit(new Writer(writeFlusher, new FutureCallback()));
try
{
executor.submit(new Writer(writeFlusher, new FutureCallback())).get();
}
catch (ExecutionException e)
{
throw e.getCause();
}
}
private void endPointFlushExpectation(final CountDownLatch writeCalledLatch,
final CountDownLatch failedCalledLatch) throws IOException
{
when(_endPointMock.flush(any(ByteBuffer[].class))).thenAnswer(new Answer<Object>()
{
int called = 0;
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
called++;
Object[] arguments = invocation.getArguments();
ByteBuffer byteBuffer = (ByteBuffer)arguments[0];
BufferUtil.flipToFill(byteBuffer); // pretend everything has been written
writeCalledLatch.countDown();
failedCalledLatch.await(5, TimeUnit.SECONDS);
return null;
}
});
}
@Test
@Ignore
public void testConcurrentAccessToIncompleteWriteAndFailed() throws IOException, InterruptedException, ExecutionException
{
ExecutorService executor = Executors.newFixedThreadPool(16);
final CountDownLatch failedCalledLatch = new CountDownLatch(1);
final CountDownLatch onIncompleteFlushedCalledLatch = new CountDownLatch(1);
final CountDownLatch writeCalledLatch = new CountDownLatch(1);
final CountDownLatch completeWrite = new CountDownLatch(1);
final WriteFlusher writeFlusher = new WriteFlusher(_endPointMock)
{
protected void onIncompleteFlushed()
{
onIncompleteFlushedCalledLatch.countDown();
completeWrite();
completeWrite.countDown();
}
};
endPointFlushExpectationPendingWrite(writeCalledLatch, failedCalledLatch);
ExposingStateCallback callback = new ExposingStateCallback();
executor.submit(new Writer(writeFlusher, callback));
assertThat("Write has been called.", writeCalledLatch.await(5, TimeUnit.SECONDS), is(true));
executor.submit(new FailedCaller(writeFlusher, failedCalledLatch));
assertThat("Failed has been called.", failedCalledLatch.await(5, TimeUnit.SECONDS), is(true));
writeFlusher.write(_context, new FutureCallback<String>(), BufferUtil.toBuffer("foobar"));
assertThat("completeWrite done", completeWrite.await(5, TimeUnit.SECONDS), is(true));
}
//TODO: combine with endPointFlushExpectation
private void endPointFlushExpectationPendingWrite(final CountDownLatch writeCalledLatch, final CountDownLatch
failedCalledLatch)
throws
IOException
{
when(_endPointMock.flush(any(ByteBuffer[].class))).thenAnswer(new Answer<Object>()
{
@Override
public Object answer(InvocationOnMock invocation) throws Throwable
{
writeCalledLatch.countDown();
Object[] arguments = invocation.getArguments();
ByteBuffer byteBuffer = (ByteBuffer)arguments[0];
int oldPos = byteBuffer.position();
if (byteBuffer.remaining() == 2)
{
// make sure failed is called before we go on
failedCalledLatch.await(5, TimeUnit.SECONDS);
BufferUtil.flipToFill(byteBuffer);
}
else if (byteBuffer.remaining() == 3)
{
byteBuffer.position(1); // pretend writing one byte
return 1;
}
else
{
byteBuffer.position(byteBuffer.limit());
}
return byteBuffer.limit() - oldPos;
}
});
}
private static class FailedCaller implements Callable
{
private final WriteFlusher writeFlusher;
private CountDownLatch failedCalledLatch;
public FailedCaller(WriteFlusher writeFlusher, CountDownLatch failedCalledLatch)
{
this.writeFlusher = writeFlusher;
this.failedCalledLatch = failedCalledLatch;
}
@Override
public FutureCallback call()
{
writeFlusher.onFail(new IllegalStateException());
failedCalledLatch.countDown();
return null;
}
}
private class Writer implements Callable
{
private final WriteFlusher writeFlusher;
private FutureCallback<String> callback;
public Writer(WriteFlusher writeFlusher, FutureCallback callback)
{
this.writeFlusher = writeFlusher;
this.callback = callback;
}
@Override
public FutureCallback call()
{
writeFlusher.write(_context, callback, BufferUtil.toBuffer("foo"));
return callback;
}
}
}

View File

@ -0,0 +1,2 @@
org.eclipse.jetty.util.log.class=org.eclipse.jetty.util.log.StdErrLog
org.eclipse.jetty.io.LEVEL=WARN

View File

@ -18,13 +18,10 @@ import static org.junit.Assert.assertTrue;
import java.lang.management.ManagementFactory;
import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.ReflectionException;
import junit.framework.Assert;

View File

@ -26,7 +26,7 @@ public class ProxyServer
public static void main(String[] args) throws Exception
{
Server server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
SelectChannelConnector connector = new SelectChannelConnector(server);
connector.setPort(8888);
server.addConnector(connector);

View File

@ -23,8 +23,9 @@ import org.eclipse.jetty.http.HttpCookie;
import org.eclipse.jetty.http.HttpMethods;
import org.eclipse.jetty.io.Buffer;
import org.eclipse.jetty.proxy.BalancerServlet;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.session.HashSessionIdManager;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
@ -103,7 +104,7 @@ public abstract class AbstractBalancerServletTest
private Server createServer(ServletHolder servletHolder, String appContext, String servletUrlPattern)
{
Server server = new Server();
SelectChannelConnector httpConnector = new SelectChannelConnector();
SelectChannelConnector httpConnector = new SelectChannelConnector(server);
server.addConnector(httpConnector);
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
@ -122,9 +123,9 @@ public abstract class AbstractBalancerServletTest
node.setSessionIdManager(sessionIdManager);
}
private int getServerPort(Server node)
private int getServerPort(Server server)
{
return node.getConnectors()[0].getLocalPort();
return ((Connector.NetConnector)server.getConnectors()[0]).getLocalPort();
}
protected byte[] sendRequestToBalancer(String requestUri) throws IOException, InterruptedException

View File

@ -76,8 +76,8 @@
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<groupId>org.eclipse.jetty.toolchain</groupId>
<artifactId>jetty-test-helper</artifactId>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -26,7 +26,7 @@ import java.util.concurrent.CopyOnWriteArraySet;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.server.HttpConnector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.UserIdentity;
@ -355,7 +355,7 @@ public class ConstraintSecurityHandler extends SecurityHandler implements Constr
return true;
}
HttpConnector connector = HttpChannel.getCurrentHttpChannel().getHttpConnector();
HttpConfiguration connector = HttpChannel.getCurrentHttpChannel().getHttpConfiguration();
if (dataConstraint == UserDataConstraint.Integral)
{

View File

@ -17,6 +17,7 @@
package org.eclipse.jetty.security;
import java.util.Properties;
import javax.security.auth.Subject;
import org.eclipse.jetty.server.UserIdentity;

View File

@ -16,6 +16,7 @@ package org.eclipse.jetty.security.authentication;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.security;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
@ -32,7 +33,7 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.security.authentication.FormAuthenticator;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.LocalHttpConnector;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.UserIdentity;
@ -43,7 +44,9 @@ import org.eclipse.jetty.server.session.SessionHandler;
import org.eclipse.jetty.util.B64Code;
import org.eclipse.jetty.util.security.Constraint;
import org.eclipse.jetty.util.security.Password;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@ -54,16 +57,16 @@ import org.junit.Test;
public class ConstraintTest
{
private static final String TEST_REALM = "TestRealm";
private static Server _server;
private static LocalHttpConnector _connector;
private static SessionHandler _session;
private Server _server;
private LocalConnector _connector;
private SessionHandler _session;
private ConstraintSecurityHandler _security;
@BeforeClass
public static void startServer()
@Before
public void startServer()
{
_server = new Server();
_connector = new LocalHttpConnector();
_connector = new LocalConnector(_server);
_server.setConnectors(new Connector[]{_connector});
ContextHandler _context = new ContextHandler();
@ -79,11 +82,7 @@ public class ConstraintTest
_context.setHandler(_session);
_server.addBean(_loginService);
}
@Before
public void setupSecurity()
{
_security = new ConstraintSecurityHandler();
_session.setHandler(_security);
RequestHandler _handler = new RequestHandler();
@ -192,52 +191,52 @@ public class ConstraintTest
String response;
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/forbid/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
assertThat(response,startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response,containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
assertThat(response,startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response,containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
// test admin
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
assertThat(response,startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response,containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("admin:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
assertThat(response,startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response,containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 "));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403 "));
assertThat(response,containsString("!role"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/admin/relax/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
}
@Test
@ -250,10 +249,10 @@ public class ConstraintTest
String response;
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/forbid/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertThat(response,containsString("Cache-Control: no-cache"));
@ -268,7 +267,7 @@ public class ConstraintTest
"Content-Length: 31\r\n" +
"\r\n" +
"j_username=user&j_password=wrong\r\n");
assertTrue(response.indexOf("testErrorPage") > 0);
assertThat(response,containsString("testErrorPage"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
@ -276,21 +275,22 @@ public class ConstraintTest
"Content-Length: 35\r\n" +
"\r\n" +
"j_username=user&j_password=password\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("/ctx/auth/info") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("Location"));
assertThat(response,containsString("Location"));
assertThat(response,containsString("/ctx/auth/info"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403"));
assertThat(response,containsString("!role"));
}
@Test
@ -303,21 +303,21 @@ public class ConstraintTest
String response;
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/forbid/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertTrue(response.indexOf(" 302 Found") > 0);
assertTrue(response.indexOf("/ctx/testLoginPage") > 0);
assertThat(response,containsString(" 302 Found"));
assertThat(response,containsString("/ctx/testLoginPage"));
String session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/testLoginPage HTTP/1.0\r\n"+
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.indexOf(" 200 OK") > 0);
assertTrue(response.indexOf("URI=/ctx/testLoginPage") > 0);
assertThat(response,containsString(" 200 OK"));
assertThat(response,containsString("URI=/ctx/testLoginPage"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
@ -325,7 +325,7 @@ public class ConstraintTest
"Content-Length: 31\r\n" +
"\r\n" +
"j_username=user&j_password=wrong\r\n");
assertTrue(response.indexOf("Location") > 0);
assertThat(response,containsString("Location"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
@ -333,21 +333,21 @@ public class ConstraintTest
"Content-Length: 35\r\n" +
"\r\n" +
"j_username=user&j_password=password\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("/ctx/auth/info") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("Location"));
assertThat(response,containsString("/ctx/auth/info"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403"));
assertThat(response,containsString("!role"));
}
@Test
@ -360,25 +360,25 @@ public class ConstraintTest
String response;
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/forbid/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
response = _connector.getResponses("POST /ctx/auth/info HTTP/1.0\r\n"+
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Content-Length: 27\r\n" +
"\r\n" +
"test_parameter=test_value\r\n");
assertTrue(response.indexOf(" 302 Found") > 0);
assertTrue(response.indexOf("/ctx/testLoginPage") > 0);
assertThat(response,containsString(" 302 Found"));
assertThat(response,containsString("/ctx/testLoginPage"));
String session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/testLoginPage HTTP/1.0\r\n"+
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.indexOf(" 200 OK") > 0);
assertTrue(response.indexOf("URI=/ctx/testLoginPage") > 0);
assertThat(response,containsString(" 200 OK"));
assertThat(response,containsString("URI=/ctx/testLoginPage"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
@ -386,7 +386,7 @@ public class ConstraintTest
"Content-Length: 31\r\n" +
"\r\n" +
"j_username=user&j_password=wrong\r\n");
assertTrue(response.indexOf("Location") > 0);
assertThat(response,containsString("Location"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
@ -394,30 +394,30 @@ public class ConstraintTest
"Content-Length: 35\r\n" +
"\r\n" +
"j_username=user&j_password=password\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("/ctx/auth/info") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("Location"));
assertThat(response,containsString("/ctx/auth/info"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
// sneak in other request
response = _connector.getResponses("GET /ctx/auth/other HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
assertTrue(!response.contains("test_value"));
// retry post as GET
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
assertTrue(response.contains("test_value"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403"));
assertThat(response,containsString("!role"));
}
@Test
@ -430,47 +430,47 @@ public class ConstraintTest
String response;
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/forbid/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertTrue(response.indexOf(" 302 Found") > 0);
assertTrue(response.indexOf("/ctx/testLoginPage") > 0);
assertThat(response,containsString(" 302 Found"));
assertThat(response,containsString("/ctx/testLoginPage"));
int jsession=response.indexOf(";jsessionid=");
String session = response.substring(jsession + 12, response.indexOf("\r\n",jsession));
response = _connector.getResponses("GET /ctx/testLoginPage;jsessionid="+session+";other HTTP/1.0\r\n"+
"\r\n");
assertTrue(response.indexOf(" 200 OK") > 0);
assertTrue(response.indexOf("URI=/ctx/testLoginPage") > 0);
assertThat(response,containsString(" 200 OK"));
assertThat(response,containsString("URI=/ctx/testLoginPage"));
response = _connector.getResponses("POST /ctx/j_security_check;jsessionid="+session+";other HTTP/1.0\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Content-Length: 31\r\n" +
"\r\n" +
"j_username=user&j_password=wrong\r\n");
assertTrue(response.indexOf("Location") > 0);
assertThat(response,containsString("Location"));
response = _connector.getResponses("POST /ctx/j_security_check;jsessionid="+session+";other HTTP/1.0\r\n" +
"Content-Type: application/x-www-form-urlencoded\r\n" +
"Content-Length: 35\r\n" +
"\r\n" +
"j_username=user&j_password=password\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("/ctx/auth/info") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("Location"));
assertThat(response,containsString("/ctx/auth/info"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/auth/info;jsessionid="+session+";other HTTP/1.0\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/admin/info;jsessionid="+session+";other HTTP/1.0\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403"));
assertThat(response,containsString("!role"));
}
@Test
@ -481,58 +481,58 @@ public class ConstraintTest
String response;
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/forbid/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
assertThat(response,startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response,containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
assertThat(response,startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response,containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertThat(response,startsWith("HTTP/1.1 403"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
// test admin
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
assertThat(response,startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response,containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("admin:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 401 Unauthorized"));
assertTrue(response.indexOf("WWW-Authenticate: basic realm=\"TestRealm\"") > 0);
assertThat(response,startsWith("HTTP/1.1 401 Unauthorized"));
assertThat(response,containsString("WWW-Authenticate: basic realm=\"TestRealm\""));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 "));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403 "));
assertThat(response,containsString("!role"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/admin/relax/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
}
@Test
@ -545,17 +545,17 @@ public class ConstraintTest
String response;
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/forbid/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
// assertTrue(response.indexOf(" 302 Found") > 0);
// assertTrue(response.indexOf("/ctx/testLoginPage") > 0);
assertTrue(response.indexOf("Cache-Control: no-cache") > 0);
assertTrue(response.indexOf("Expires") > 0);
assertTrue(response.indexOf("URI=/ctx/testLoginPage") > 0);
// assertThat(response,containsString(" 302 Found"));
// assertThat(response,containsString("/ctx/testLoginPage"));
assertThat(response,containsString("Cache-Control: no-cache"));
assertThat(response,containsString("Expires"));
assertThat(response,containsString("URI=/ctx/testLoginPage"));
String session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
@ -565,8 +565,8 @@ public class ConstraintTest
"Content-Length: 31\r\n" +
"\r\n" +
"j_username=user&j_password=wrong\r\n");
// assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("testErrorPage") > 0);
// assertThat(response,containsString("Location"));
assertThat(response,containsString("testErrorPage"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
@ -574,29 +574,29 @@ public class ConstraintTest
"Content-Length: 35\r\n" +
"\r\n" +
"j_username=user&j_password=password\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("/ctx/auth/info") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("Location"));
assertThat(response,containsString("/ctx/auth/info"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403"));
assertThat(response,containsString("!role"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403"));
assertThat(response,containsString("!role"));
// log in again as user2
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
// assertTrue(response.startsWith("HTTP/1.1 302 "));
// assertTrue(response.indexOf("testLoginPage") > 0);
// assertThat(response,startsWith("HTTP/1.1 302 "));
// assertThat(response,containsString("testLoginPage"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
@ -605,28 +605,28 @@ public class ConstraintTest
"Content-Length: 36\r\n" +
"\r\n" +
"j_username=user2&j_password=password\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("/ctx/auth/info") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("Location"));
assertThat(response,containsString("/ctx/auth/info"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403"));
assertThat(response,containsString("!role"));
// log in again as admin
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
// assertTrue(response.startsWith("HTTP/1.1 302 "));
// assertTrue(response.indexOf("testLoginPage") > 0);
// assertThat(response,startsWith("HTTP/1.1 302 "));
// assertThat(response,containsString("testLoginPage"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
@ -635,20 +635,20 @@ public class ConstraintTest
"Content-Length: 36\r\n" +
"\r\n" +
"j_username=admin&j_password=password\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("/ctx/auth/info") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("Location"));
assertThat(response,containsString("/ctx/auth/info"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
}
@Test
@ -660,14 +660,14 @@ public class ConstraintTest
String response;
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/forbid/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 Forbidden"));
assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertTrue(response.indexOf(" 302 Found") > 0);
assertTrue(response.indexOf("/ctx/testLoginPage") > 0);
assertThat(response,containsString(" 302 Found"));
assertThat(response,containsString("/ctx/testLoginPage"));
String session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
@ -677,7 +677,7 @@ public class ConstraintTest
"Content-Length: 31\r\n" +
"\r\n" +
"j_username=user&j_password=wrong\r\n");
assertTrue(response.indexOf("Location") > 0);
assertThat(response,containsString("Location"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
@ -685,29 +685,29 @@ public class ConstraintTest
"Content-Length: 35\r\n" +
"\r\n" +
"j_username=user&j_password=password\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("/ctx/auth/info") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("Location"));
assertThat(response,containsString("/ctx/auth/info"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403"));
assertThat(response,containsString("!role"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403"));
assertThat(response,containsString("!role"));
// log in again as user2
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("testLoginPage") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("testLoginPage"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
@ -716,29 +716,29 @@ public class ConstraintTest
"Content-Length: 36\r\n" +
"\r\n" +
"j_username=user2&j_password=password\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("/ctx/auth/info") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("Location"));
assertThat(response,containsString("/ctx/auth/info"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 403"));
assertTrue(response.indexOf("!role") > 0);
assertThat(response,startsWith("HTTP/1.1 403"));
assertThat(response,containsString("!role"));
// log in again as admin
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
// assertTrue(response.startsWith("HTTP/1.1 302 "));
// assertTrue(response.indexOf("testLoginPage") > 0);
// assertThat(response,startsWith("HTTP/1.1 302 "));
// assertThat(response,containsString("testLoginPage"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("POST /ctx/j_security_check HTTP/1.0\r\n" +
@ -747,20 +747,20 @@ public class ConstraintTest
"Content-Length: 36\r\n" +
"\r\n" +
"j_username=admin&j_password=password\r\n");
assertTrue(response.startsWith("HTTP/1.1 302 "));
assertTrue(response.indexOf("Location") > 0);
assertTrue(response.indexOf("/ctx/auth/info") > 0);
assertThat(response,startsWith("HTTP/1.1 302 "));
assertThat(response,containsString("Location"));
assertThat(response,containsString("/ctx/auth/info"));
session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/admin/info HTTP/1.0\r\n" +
"Cookie: JSESSIONID=" + session + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
}
@Test
@ -774,12 +774,12 @@ public class ConstraintTest
String response;
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 500 "));
assertThat(response,startsWith("HTTP/1.1 500 "));
_server.stop();
@ -792,7 +792,7 @@ public class ConstraintTest
response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n" +
"Authorization: Basic " + B64Code.encode("user2:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertThat(response,startsWith("HTTP/1.1 200 OK"));
}
@Test
@ -806,20 +806,20 @@ public class ConstraintTest
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n"+
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertTrue(response.indexOf("user=null") > 0);
assertThat(response,startsWith("HTTP/1.1 200 OK"));
assertThat(response,containsString("user=null"));
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n"+
"Authorization: Basic " + B64Code.encode("admin:wrong") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertTrue(response.indexOf("user=null") > 0);
assertThat(response,startsWith("HTTP/1.1 200 OK"));
assertThat(response,containsString("user=null"));
response = _connector.getResponses("GET /ctx/noauth/info HTTP/1.0\r\n"+
"Authorization: Basic " + B64Code.encode("admin:password") + "\r\n" +
"\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertTrue(response.indexOf("user=admin") > 0);
assertThat(response,startsWith("HTTP/1.1 200 OK"));
assertThat(response,containsString("user=admin"));
}
@Test
@ -831,13 +831,13 @@ public class ConstraintTest
String response;
response = _connector.getResponses("GET /ctx/forbid/somethig HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 403 "));
assertThat(response,startsWith("HTTP/1.1 403 "));
response = _connector.getResponses("POST /ctx/forbid/post HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 "));
assertThat(response,startsWith("HTTP/1.1 200 "));
response = _connector.getResponses("GET /ctx/forbid/post HTTP/1.0\r\n\r\n");
assertTrue(response.startsWith("HTTP/1.1 200 ")); // This is so stupid, but it is the S P E C
assertThat(response,startsWith("HTTP/1.1 200 ")); // This is so stupid, but it is the S P E C
}
private class RequestHandler extends AbstractHandler
{

View File

@ -13,8 +13,12 @@
package org.eclipse.jetty.security;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.containsString;
import java.io.IOException;
import java.util.Arrays;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -23,7 +27,8 @@ import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.security.authentication.BasicAuthenticator;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.LocalHttpConnector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.UserIdentity;
@ -35,17 +40,14 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertThat;
import static org.junit.matchers.JUnitMatchers.containsString;
/**
* @version $Revision: 1441 $ $Date: 2010-04-02 12:28:17 +0200 (Fri, 02 Apr 2010) $
*/
public class DataConstraintsTest
{
private Server _server;
private LocalHttpConnector _connector;
private LocalHttpConnector _connectorS;
private LocalConnector _connector;
private LocalConnector _connectorS;
private SessionHandler _session;
private ConstraintSecurityHandler _security;
@ -53,15 +55,15 @@ public class DataConstraintsTest
public void startServer()
{
_server = new Server();
_connector = new LocalHttpConnector();
_connector = new LocalConnector(_server);
_connector.setIdleTimeout(300000);
_connector.setIntegralPort(9998);
_connector.setIntegralScheme("FTP");
_connector.setConfidentialPort(9999);
_connector.setConfidentialScheme("SPDY");
_connectorS = new LocalHttpConnector()
_connector.getConnectionFactory().getHttpConfig().setIntegralPort(9998);
_connector.getConnectionFactory().getHttpConfig().setIntegralScheme("FTP");
_connector.getConnectionFactory().getHttpConfig().setConfidentialPort(9999);
_connector.getConnectionFactory().getHttpConfig().setConfidentialScheme("SPDY");
_connectorS = new LocalConnector(_server,
new HttpConfiguration(null,false)
{
@Override
public void customize(Request request) throws IOException
{
@ -81,7 +83,7 @@ public class DataConstraintsTest
{
return true;
}
};
});
_server.setConnectors(new Connector[]{_connector,_connectorS});
ContextHandler _context = new ContextHandler();

View File

@ -16,15 +16,23 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.Socket;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import org.eclipse.jetty.io.AsyncConnection;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.StandardByteBufferPool;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.util.annotation.Name;
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;
/**
* Abstract Connector implementation. This abstract implementation of the Connector interface provides:
@ -42,23 +50,57 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co
protected final Logger LOG = Log.getLogger(getClass());
private final Statistics _stats = new ConnectionStatistics();
private final ConnectionFactory _connectionFactory;
private final Thread[] _acceptors;
private final Executor _executor;
private final ScheduledExecutorService _scheduler;
private final Server _server;
private final ByteBufferPool _byteBufferPool;
private volatile String _name;
private volatile Server _server;
private volatile Executor _executor;
private volatile int _acceptQueueSize = 128;
private volatile boolean _reuseAddress = true;
private volatile ByteBufferPool _byteBufferPool;
private volatile long _idleTimeout = 200000;
private volatile int _soLingerTime = -1;
public AbstractConnector()
/* ------------------------------------------------------------ */
/**
* @param server The server this connector will be added to. Must not be null.
* @param connectionFactory ConnectionFactory or null for default
* @param executor An executor for this connector or null to use the servers executor
* @param scheduler A scheduler for this connector or null to use the servers scheduler
* @param pool A buffer pool for this connector or null to use a default {@link ByteBufferPool}
* @param acceptors the number of acceptor threads to use, or 0 for a default value.
*/
public AbstractConnector(
Server server,
ConnectionFactory connectionFactory,
Executor executor,
ScheduledExecutorService scheduler,
ByteBufferPool pool, int acceptors)
{
this(Math.max(1, (Runtime.getRuntime().availableProcessors()) / 4));
}
_server=server;
_executor=executor!=null?executor:_server.getThreadPool();
_scheduler=scheduler!=null?scheduler:Executors.newSingleThreadScheduledExecutor(new ThreadFactory()
{
@Override
public Thread newThread(Runnable r)
{
return new Thread(r, "Timer-" + getName());
}
});
_byteBufferPool = pool!=null?pool:new StandardByteBufferPool();
_connectionFactory=connectionFactory!=null?connectionFactory:new ConnectionFactory();
addBean(_server,false);
addBean(_executor,false);
addBean(_scheduler,scheduler==null);
addBean(_byteBufferPool,pool==null);
addBean(_connectionFactory,connectionFactory!=null);
public AbstractConnector(@Name("acceptors") int acceptors)
{
if (acceptors<=0)
acceptors=Math.max(1,(Runtime.getRuntime().availableProcessors()) / 4);
if (acceptors > 2 * Runtime.getRuntime().availableProcessors())
LOG.warn("Acceptors should be <= 2*availableProcessors: " + this);
_acceptors = new Thread[acceptors];
@ -75,45 +117,25 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co
{
return _server;
}
public void setServer(Server server)
@Override
public ConnectionFactory getConnectionFactory()
{
_server = server;
return _connectionFactory;
}
public Executor findExecutor()
{
if (_executor == null && getServer() != null)
return getServer().getThreadPool();
return _executor;
}
@Override
public Executor getExecutor()
{
return _executor;
}
public void setExecutor(Executor executor)
{
removeBean(_executor);
_executor = executor;
addBean(_executor);
}
@Override
public ByteBufferPool getByteBufferPool()
{
return _byteBufferPool;
}
public void setByteBufferPool(ByteBufferPool byteBufferPool)
{
removeBean(byteBufferPool);
_byteBufferPool = byteBufferPool;
addBean(_byteBufferPool);
}
/**
* @return Returns the maxIdleTime.
*/
@ -190,18 +212,13 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co
@Override
protected void doStart() throws Exception
{
if (_server == null)
throw new IllegalStateException("No server");
_byteBufferPool = new StandardByteBufferPool();
super.doStart();
// Start selector thread
synchronized (this)
{
for (int i = 0; i < _acceptors.length; i++)
findExecutor().execute(new Acceptor(i));
getExecutor().execute(new Acceptor(i));
}
LOG.info("Started {}", this);
@ -217,10 +234,6 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co
if (thread != null)
thread.interrupt();
}
int i = _name.lastIndexOf("/");
if (i > 0)
_name = _name.substring(0, i);
}
public void join() throws InterruptedException
@ -317,19 +330,19 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co
_name = name;
}
protected void connectionOpened(AsyncConnection connection)
protected void connectionOpened(Connection connection)
{
_stats.connectionOpened();
}
protected void connectionUpgraded(AsyncConnection oldConnection, AsyncConnection newConnection)
protected void connectionUpgraded(Connection oldConnection, Connection newConnection)
{
long duration = System.currentTimeMillis() - oldConnection.getEndPoint().getCreatedTimeStamp();
int requests = (oldConnection instanceof HttpConnection) ? ((HttpConnection)oldConnection).getHttpChannel().getRequests() : 0;
_stats.connectionUpgraded(duration, requests, requests);
}
protected void connectionClosed(AsyncConnection connection)
protected void connectionClosed(Connection connection)
{
long duration = System.currentTimeMillis() - connection.getEndPoint().getCreatedTimeStamp();
// TODO: remove casts to HttpConnection
@ -352,4 +365,9 @@ public abstract class AbstractConnector extends AggregateLifeCycle implements Co
{
_reuseAddress = reuseAddress;
}
public ScheduledExecutorService getScheduler()
{
return _scheduler;
}
}

View File

@ -14,19 +14,20 @@
package org.eclipse.jetty.server;
import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public abstract class AbstractNetConnector extends AbstractConnector implements Connector.NetConnector
{
private volatile String _host;
private volatile int _port = 0;
protected AbstractNetConnector()
public AbstractNetConnector(Server server, ConnectionFactory connectionFactory, Executor executor, ScheduledExecutorService scheduler, ByteBufferPool pool, int acceptors)
{
}
protected AbstractNetConnector(int acceptors)
{
super(acceptors);
super(server,connectionFactory,executor,scheduler,pool, acceptors);
}
public void setHost(String host)
@ -34,6 +35,7 @@ public abstract class AbstractNetConnector extends AbstractConnector implements
_host = host;
}
@Override
public String getHost()
{
return _host;
@ -44,11 +46,13 @@ public abstract class AbstractNetConnector extends AbstractConnector implements
_port = port;
}
@Override
public int getPort()
{
return _port;
}
@Override
public int getLocalPort()
{
return -1;
@ -79,12 +83,18 @@ public abstract class AbstractNetConnector extends AbstractConnector implements
LOG.warn(e);
}
super.doStop();
int i = getName().lastIndexOf("/");
if (i > 0)
setName(getName().substring(0, i));
}
@Override
public void open() throws IOException
{
}
@Override
public void close() throws IOException
{
}

View File

@ -0,0 +1,92 @@
// ========================================================================
// Copyright (c) 2004-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server;
import java.io.IOException;
import javax.net.ssl.SSLEngine;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;
// TODO This is just a place holder for a real factory
public class ConnectionFactory extends AggregateLifeCycle
{
private final boolean _ssl;
private final SslContextFactory _sslContextFactory;
// TODO Make this part of pluggable factory
private final HttpConfiguration _httpConfig;
ConnectionFactory()
{
this(null,false);
}
/* ------------------------------------------------------------ */
/**
* @param sslContextFactory An SslContextFactory to use or null if no ssl is required or to use default {@link SslContextFactory}
* @param ssl If true, then new connections will assumed to be SSL. If false, connections can only become SSL if they upgrade and a SslContextFactory is passed.
*/
ConnectionFactory(SslContextFactory sslContextFactory, boolean ssl)
{
this(null,sslContextFactory,ssl);
}
ConnectionFactory(HttpConfiguration httpConfig, SslContextFactory sslContextFactory, boolean ssl)
{
_ssl=ssl;
_sslContextFactory=sslContextFactory!=null?sslContextFactory:(ssl?new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH):null);
addBean(_sslContextFactory,sslContextFactory==null);
// TODO make this pluggable
_httpConfig = httpConfig!=null?httpConfig:new HttpConfiguration(_sslContextFactory,ssl);
addBean(_httpConfig,httpConfig==null);
}
protected Connection newConnection(Connector connector,EndPoint endp) throws IOException
{
if (_ssl)
{
SSLEngine engine = _sslContextFactory.createSSLEngine(endp.getRemoteAddress());
SslConnection ssl_connection = new SslConnection(connector.getByteBufferPool(), connector.getExecutor(), endp, engine);
Connection http_connection = new HttpConnection(_httpConfig,connector,ssl_connection.getDecryptedEndPoint());
ssl_connection.getDecryptedEndPoint().setConnection(http_connection);
return ssl_connection;
}
return new HttpConnection(_httpConfig,connector,endp);
}
public SslContextFactory getSslContextFactory()
{
return _sslContextFactory;
}
public HttpConfiguration getHttpConfig()
{
return _httpConfig;
}
}

View File

@ -1,3 +1,16 @@
// ========================================================================
// Copyright (c) 2004-2012 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server;
import java.util.concurrent.atomic.AtomicLong;

View File

@ -1,5 +1,5 @@
// ========================================================================
// Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
// Copyright (c) 2004-2012 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
@ -15,9 +15,11 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.ssl.SslContextFactory;
/** HTTP Connector.
* Implementations of this interface provide connectors for the HTTP protocol.
@ -42,14 +44,17 @@ public interface Connector extends LifeCycle
Server getServer();
/* ------------------------------------------------------------ */
Executor findExecutor();
ConnectionFactory getConnectionFactory();
/* ------------------------------------------------------------ */
Executor getExecutor();
/* ------------------------------------------------------------ */
ScheduledExecutorService getScheduler();
/* ------------------------------------------------------------ */
ByteBufferPool getByteBufferPool();
/* ------------------------------------------------------------ */
/**
* @return Max Idle time for connections in milliseconds

View File

@ -19,6 +19,7 @@ import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.concurrent.ScheduledExecutorService;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
@ -36,8 +37,8 @@ import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.io.UncheckedPrintWriter;
import org.eclipse.jetty.util.BufferUtil;
@ -71,7 +72,7 @@ public abstract class HttpChannel
private final Server _server;
private final AsyncConnection _connection;
private final Connection _connection;
private final HttpURI _uri;
private final ChannelEventHandler _handler = new ChannelEventHandler();
@ -99,7 +100,7 @@ public abstract class HttpChannel
/* ------------------------------------------------------------ */
public HttpChannel(Server server,AsyncConnection connection,HttpInput input)
public HttpChannel(Server server,Connection connection,HttpInput input)
{
_server = server;
_connection = connection;
@ -126,7 +127,7 @@ public abstract class HttpChannel
}
/* ------------------------------------------------------------ */
public AsyncEndPoint getEndPoint()
public EndPoint getEndPoint()
{
return getConnection().getEndPoint();
}
@ -189,7 +190,7 @@ public abstract class HttpChannel
}
/* ------------------------------------------------------------ */
public AsyncConnection getConnection()
public Connection getConnection()
{
return _connection;
}
@ -330,7 +331,7 @@ public abstract class HttpChannel
if (_state.isInitial())
{
_request.setDispatcherType(DispatcherType.REQUEST);
getHttpConnector().customize(_request);
getHttpConfiguration().customize(_request);
getServer().handle(this);
}
else
@ -380,6 +381,7 @@ public abstract class HttpChannel
{
try
{
_state.completed();
if (_expect100Continue)
{
LOG.debug("100 continues not sent");
@ -413,7 +415,6 @@ public abstract class HttpChannel
}
finally
{
_state.completed();
_request.setHandled(true);
completed();
}
@ -790,7 +791,9 @@ public abstract class HttpChannel
}
}
public abstract HttpConnector getHttpConnector();
public abstract Connector getConnector();
public abstract HttpConfiguration getHttpConfiguration();
protected abstract int write(ByteBuffer content) throws IOException;

View File

@ -18,6 +18,7 @@ import java.util.List;
import java.util.concurrent.Future;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import javax.servlet.AsyncContext;
import javax.servlet.AsyncEvent;
import javax.servlet.AsyncListener;

View File

@ -2,26 +2,35 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
import javax.servlet.ServletRequest;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.server.ssl.SslCertificates;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public abstract class HttpConnector extends AbstractNetConnector
public class HttpConfiguration extends AggregateLifeCycle
{
static final Logger LOG = Log.getLogger(HttpConfiguration.class);
private final SslContextFactory _sslContextFactory;
private final boolean _ssl;
private String _integralScheme = HttpScheme.HTTPS.asString();
private int _integralPort = 0;
private String _confidentialScheme = HttpScheme.HTTPS.asString();
private int _confidentialPort = 0;
private boolean _forwarded;
private String _hostHeader;
private ScheduledExecutorService _scheduler;
private boolean _shutdownScheduler;
private String _forwardedHostHeader = HttpHeader.X_FORWARDED_HOST.toString();
private String _forwardedServerHeader = HttpHeader.X_FORWARDED_SERVER.toString();
private String _forwardedForHeader = HttpHeader.X_FORWARDED_FOR.toString();
@ -32,51 +41,23 @@ public abstract class HttpConnector extends AbstractNetConnector
private int _requestBufferSize=16*1024;
private int _responseHeaderSize=6*1024;
private int _responseBufferSize=16*1024;
public HttpConnector()
public HttpConfiguration(SslContextFactory sslContextFactory,boolean ssl)
{
_sslContextFactory=sslContextFactory!=null?sslContextFactory:ssl?new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH):null;
_ssl=ssl;
if (_sslContextFactory!=null)
addBean(_sslContextFactory,sslContextFactory==null);
}
public SslContextFactory getSslContextFactory()
{
return _sslContextFactory;
}
public HttpConnector(int acceptors)
public boolean isSecure()
{
super(acceptors);
}
public ScheduledExecutorService getScheduler()
{
return _scheduler;
}
public void setScheduler(ScheduledExecutorService scheduler)
{
_scheduler = scheduler;
}
@Override
protected void doStart() throws Exception
{
super.doStart();
if (_scheduler == null)
{
_scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory()
{
@Override
public Thread newThread(Runnable r)
{
return new Thread(r, "Timer-" + HttpConnector.this.getName());
}
});
_shutdownScheduler = true;
}
}
@Override
protected void doStop() throws Exception
{
if (_shutdownScheduler)
_scheduler.shutdownNow();
_scheduler = null;
super.doStop();
return _ssl;
}
public int getRequestHeaderSize()
@ -120,8 +101,37 @@ public abstract class HttpConnector extends AbstractNetConnector
}
/* ------------------------------------------------------------ */
/**
* Allow the Listener a chance to customise the request. before the server
* does its stuff. <br>
* This allows the required attributes to be set for SSL requests. <br>
* The requirements of the Servlet specs are:
* <ul>
* <li> an attribute named "javax.servlet.request.ssl_session_id" of type
* String (since Servlet Spec 3.0).</li>
* <li> an attribute named "javax.servlet.request.cipher_suite" of type
* String.</li>
* <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li>
* <li> an attribute named "javax.servlet.request.X509Certificate" of type
* java.security.cert.X509Certificate[]. This is an array of objects of type
* X509Certificate, the order of this array is defined as being in ascending
* order of trust. The first certificate in the chain is the one set by the
* client, the next is the one used to authenticate the first, and so on.
* </li>
* </ul>
*/
public void customize(Request request) throws IOException
{
{
if (isSecure())
{
request.setScheme(HttpScheme.HTTPS.asString());
SslConnection.DecryptedEndPoint ssl_endp = (SslConnection.DecryptedEndPoint)request.getHttpChannel().getEndPoint();
SslConnection sslConnection = ssl_endp.getSslConnection();
SSLEngine sslEngine=sslConnection.getSSLEngine();
SslCertificates.customize(sslEngine,request);
}
request.setTimeStamp(System.currentTimeMillis());
if (isForwarded())
checkForwardedHeaders(request);
}
@ -230,12 +240,23 @@ public abstract class HttpConnector extends AbstractNetConnector
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.Connector#isConfidential(org.eclipse.jetty.server .Request)
/**
* The request is integral IFF it is secure AND the server port
* matches any configured {@link #getIntegralPort()}.
* This allows separation of listeners providing INTEGRAL versus
* CONFIDENTIAL constraints, such as one SSL listener configured to require
* client certs providing CONFIDENTIAL, whereas another SSL listener not
* requiring client certs providing mere INTEGRAL constraints.
* <p>
* The request is secure if it is SSL or it {@link #isForwarded()} is true
* and the scheme matches {@link #getIntegralScheme()()}
*/
public boolean isIntegral(Request request)
{
return false;
boolean https = isSecure() || _forwarded && _integralScheme.equalsIgnoreCase(request.getScheme());
int iPort=getIntegralPort();
boolean port = iPort<=0||iPort==request.getServerPort();
return https && port;
}
/* ------------------------------------------------------------ */
@ -257,12 +278,23 @@ public abstract class HttpConnector extends AbstractNetConnector
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.jetty.server.Connector#isConfidential(org.eclipse.jetty.server.Request)
/**
* The request is confidential IFF it is secure AND the server port
* matches any configured {@link #getConfidentialPort()}.
* This allows separation of listeners providing INTEGRAL versus
* CONFIDENTIAL constraints, such as one SSL listener configured to require
* client certs providing CONFIDENTIAL, whereas another SSL listener not
* requiring client certs providing mere INTEGRAL constraints.
* <p>
* The request is secure if it is SSL or it {@link #isForwarded()} is true
* and the scheme matches {@link #getConfidentialScheme()}
*/
public boolean isConfidential(Request request)
{
return _forwarded && request.getScheme().equalsIgnoreCase(HttpScheme.HTTPS.toString());
boolean https = isSecure() || _forwarded && _confidentialScheme.equalsIgnoreCase(request.getScheme());
int confidentialPort=getConfidentialPort();
boolean port = confidentialPort<=0||confidentialPort==request.getServerPort();
return https && port;
}
/* ------------------------------------------------------------ */
@ -478,4 +510,30 @@ public abstract class HttpConnector extends AbstractNetConnector
{
_forwardedSslSessionIdHeader = forwardedSslSessionId;
}
/* ------------------------------------------------------------ */
@Override
protected void doStart() throws Exception
{
if (_sslContextFactory!=null)
{
_sslContextFactory.checkKeyStore();
super.doStart();
SSLEngine sslEngine = _sslContextFactory.newSslEngine();
sslEngine.setUseClientMode(false);
SSLSession sslSession = sslEngine.getSession();
if (getRequestHeaderSize()<sslSession.getApplicationBufferSize())
setRequestHeaderSize(sslSession.getApplicationBufferSize());
if (getRequestBufferSize()<sslSession.getApplicationBufferSize())
setRequestBufferSize(sslSession.getApplicationBufferSize());
}
else
super.doStart();
}
}

View File

@ -24,9 +24,9 @@ import org.eclipse.jetty.http.HttpGenerator.Action;
import org.eclipse.jetty.http.HttpGenerator.ResponseInfo;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.io.AbstractAsyncConnection;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.EofException;
import org.eclipse.jetty.util.BufferUtil;
@ -37,7 +37,7 @@ import org.eclipse.jetty.util.log.Logger;
/**
* A Connection that handles the HTTP protocol
*/
public class HttpConnection extends AbstractAsyncConnection
public class HttpConnection extends AbstractConnection
{
public static final Logger LOG = Log.getLogger(HttpConnection.class);
@ -46,7 +46,8 @@ public class HttpConnection extends AbstractAsyncConnection
public static final String UPGRADE_CONNECTION_ATTR = "org.eclispe.jetty.server.HttpConnection.UPGRADE";
private final Server _server;
private final HttpConnector _connector;
private final HttpConfiguration _httpConfig;
private final Connector _connector;
private final HttpParser _parser;
private final HttpGenerator _generator;
private final HttpChannel _channel;
@ -74,17 +75,18 @@ public class HttpConnection extends AbstractAsyncConnection
}
/* ------------------------------------------------------------ */
public HttpConnection(HttpConnector connector, AsyncEndPoint endpoint, Server server)
public HttpConnection(HttpConfiguration config, Connector connector, EndPoint endpoint)
{
super(endpoint,connector.findExecutor());
super(endpoint,connector.getExecutor());
_httpConfig=config;
_connector = connector;
_bufferPool=_connector.getByteBufferPool();
_server = server;
_server = connector.getServer();
_httpInput = new HttpHttpInput();
_channel = new HttpChannelOverHttp(server);
_channel = new HttpChannelOverHttp(connector.getServer());
_parser = new HttpParser(_channel.getEventHandler());
_generator = new HttpGenerator();
@ -193,7 +195,7 @@ public class HttpConnection extends AbstractAsyncConnection
/* ------------------------------------------------------------ */
/** Parse and handle HTTP messages.
* <p>
* This method is normally called as the {@link AbstractAsyncConnection} onReadable callback.
* This method is normally called as the {@link AbstractConnection} onReadable callback.
* However, it can also be called {@link HttpChannelOverHttp#completed()} if there is unconsumed
* data in the _requestBuffer, as a result of resuming a suspended request when there is a pipelined
* request already read into the buffer.
@ -210,7 +212,7 @@ public class HttpConnection extends AbstractAsyncConnection
{
setCurrentConnection(this);
// TODO try to generalize this loop into AbstractAsyncConnection
// TODO try to generalize this loop into AbstractConnection
while (true)
{
// synchronized (_lock)
@ -220,7 +222,7 @@ public class HttpConnection extends AbstractAsyncConnection
if (BufferUtil.isEmpty(_requestBuffer))
{
if (_requestBuffer==null)
_requestBuffer=_bufferPool.acquire(_connector.getRequestHeaderSize(),false);
_requestBuffer=_bufferPool.acquire(_httpConfig.getRequestHeaderSize(),false);
int filled=getEndPoint().fill(_requestBuffer);
@ -277,10 +279,10 @@ public class HttpConnection extends AbstractAsyncConnection
}
// return if the connection has been changed
if (getEndPoint().getAsyncConnection()!=this)
if (getEndPoint().getConnection()!=this)
return;
}
else if (_headerBytes>= _connector.getRequestHeaderSize())
else if (_headerBytes>= _httpConfig.getRequestHeaderSize())
{
_parser.reset();
_parser.close();
@ -306,14 +308,21 @@ public class HttpConnection extends AbstractAsyncConnection
{
setCurrentConnection(null);
}
}
/* ------------------------------------------------------------ */
@Override
public void onOpen()
{
super.onOpen();
fillInterested();
}
/* ------------------------------------------------------------ */
@Override
public void onClose()
{
super.onClose();
_channel.onClose();
}
@ -346,7 +355,7 @@ public class HttpConnection extends AbstractAsyncConnection
{
if (_responseBuffer!=null && _responseBuffer.capacity()>=size)
return;
if (_responseBuffer==null && _connector.getResponseBufferSize()>=size)
if (_responseBuffer==null && _httpConfig.getResponseBufferSize()>=size)
return;
ByteBuffer r=_bufferPool.acquire(size,false);
@ -365,14 +374,18 @@ public class HttpConnection extends AbstractAsyncConnection
if (buffer!=null)
return buffer.capacity();
return _connector.getResponseBufferSize();
return _httpConfig.getResponseBufferSize();
}
@Override
public HttpConnector getHttpConnector()
public Connector getConnector()
{
return _connector;
}
public HttpConfiguration getHttpConfiguration()
{
return _httpConfig;
}
@Override
protected void flushResponse() throws IOException
@ -424,11 +437,11 @@ public class HttpConnection extends AbstractAsyncConnection
// Handle connection upgrades
if (getResponse().getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101)
{
AsyncConnection connection=(AsyncConnection)getRequest().getAttribute(UPGRADE_CONNECTION_ATTR);
Connection connection=(Connection)getRequest().getAttribute(UPGRADE_CONNECTION_ATTR);
if (connection!=null)
{
LOG.debug("Upgrade from {} to {}",this,connection);
getEndPoint().setAsyncConnection(connection);
getEndPoint().setConnection(connection);
HttpConnection.this.reset();
return;
}
@ -522,15 +535,15 @@ public class HttpConnection extends AbstractAsyncConnection
_info=_channel.getEventHandler().commit();
LOG.debug("{} Gcommit {}",this,_info);
if (_responseHeader==null)
_responseHeader=_bufferPool.acquire(_connector.getResponseHeaderSize(),false);
_responseHeader=_bufferPool.acquire(_httpConfig.getResponseHeaderSize(),false);
continue;
case NEED_HEADER:
_responseHeader=_bufferPool.acquire(_connector.getResponseHeaderSize(),false);
_responseHeader=_bufferPool.acquire(_httpConfig.getResponseHeaderSize(),false);
continue;
case NEED_BUFFER:
_responseBuffer=_bufferPool.acquire(_connector.getResponseBufferSize(),false);
_responseBuffer=_bufferPool.acquire(_httpConfig.getResponseBufferSize(),false);
continue;
case NEED_CHUNK:
@ -625,15 +638,15 @@ public class HttpConnection extends AbstractAsyncConnection
case NEED_INFO:
_info=_channel.getEventHandler().commit();
if (_responseHeader==null)
_responseHeader=_bufferPool.acquire(_connector.getResponseHeaderSize(),false);
_responseHeader=_bufferPool.acquire(_httpConfig.getResponseHeaderSize(),false);
break;
case NEED_HEADER:
_responseHeader=_bufferPool.acquire(_connector.getResponseHeaderSize(),false);
_responseHeader=_bufferPool.acquire(_httpConfig.getResponseHeaderSize(),false);
break;
case NEED_BUFFER:
_responseBuffer=_bufferPool.acquire(_connector.getResponseBufferSize(),false);
_responseBuffer=_bufferPool.acquire(_httpConfig.getResponseBufferSize(),false);
break;
case NEED_CHUNK:
@ -694,7 +707,7 @@ public class HttpConnection extends AbstractAsyncConnection
@Override
protected void execute(Runnable task)
{
_connector.findExecutor().execute(task);
_connector.getExecutor().execute(task);
}
private FutureCallback<Void> write(ByteBuffer b0,ByteBuffer b1,ByteBuffer b2)
@ -767,7 +780,7 @@ public class HttpConnection extends AbstractAsyncConnection
// We will need a buffer to read into
if (_requestBuffer==null)
_requestBuffer=_bufferPool.acquire(_connector.getRequestBufferSize(),false);
_requestBuffer=_bufferPool.acquire(_httpConfig.getRequestBufferSize(),false);
int filled=getEndPoint().fill(_requestBuffer);
LOG.debug("{} block filled {}",this,filled);

View File

@ -19,27 +19,54 @@ import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.Phaser;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.io.AsyncByteArrayEndPoint;
import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
public class LocalHttpConnector extends HttpConnector
public class LocalConnector extends AbstractConnector
{
private static final Logger LOG = Log.getLogger(LocalHttpConnector.class);
private static final Logger LOG = Log.getLogger(LocalConnector.class);
private final BlockingQueue<LocalEndPoint> _connects = new LinkedBlockingQueue<>();
private volatile LocalExecutor _executor;
public LocalHttpConnector()
public LocalConnector(Server server)
{
setIdleTimeout(30000);
this(server,null,null,null,null, -1);
}
public LocalConnector(Server server, boolean ssl)
{
this(server,new ConnectionFactory(null,ssl),null,null,null,0);
manage(getConnectionFactory());
}
public LocalConnector(Server server, HttpConfiguration httpConfig)
{
this(server,new ConnectionFactory(httpConfig,null,false),null,null,null,0);
manage(getConnectionFactory());
}
public LocalConnector(Server server, SslContextFactory sslContextFactory)
{
this(server,new ConnectionFactory(sslContextFactory,sslContextFactory!=null),null,null,null,0);
manage(getConnectionFactory());
}
public LocalConnector(Server server, ConnectionFactory connectionFactory, Executor executor, ScheduledExecutorService scheduler, ByteBufferPool pool,
int acceptors)
{
super(server,connectionFactory,executor,scheduler,pool,acceptors);
setIdleTimeout(30000);
}
@Override
public Object getTransport()
{
@ -49,6 +76,9 @@ public class LocalHttpConnector extends HttpConnector
/** Sends requests and get responses based on thread activity.
* Returns all the responses received once the thread activity has
* returned to the level it was before the requests.
* <p>
* This methods waits until the connection is closed or
* is idle for 1s before returning the responses.
* @param requests the requests
* @return the responses
* @throws Exception if the requests fail
@ -59,23 +89,59 @@ public class LocalHttpConnector extends HttpConnector
return result==null?null:BufferUtil.toString(result,StringUtil.__UTF8_CHARSET);
}
/** Sends requests and get responses based on thread activity.
* Returns all the responses received once the thread activity has
* returned to the level it was before the requests.
* <p>
* This methods waits until the connection is closed or
* an idle period before returning the responses.
* @param requests the requests
* @param idleFor The time the response stream must be idle for before returning
* @param units The units of idleFor
* @return the responses
* @throws Exception if the requests fail
*/
public String getResponses(String requests,long idleFor,TimeUnit units) throws Exception
{
ByteBuffer result = getResponses(BufferUtil.toBuffer(requests,StringUtil.__UTF8_CHARSET),idleFor,units);
return result==null?null:BufferUtil.toString(result,StringUtil.__UTF8_CHARSET);
}
/** Sends requests and get's responses based on thread activity.
* Returns all the responses received once the thread activity has
* returned to the level it was before the requests.
* <p>
* This methods waits until the connection is closed or
* is idle for 1s before returning the responses.
* @param requestsBuffer the requests
* @return the responses
* @throws Exception if the requests fail
*/
public ByteBuffer getResponses(ByteBuffer requestsBuffer) throws Exception
{
return getResponses(requestsBuffer,1000,TimeUnit.MILLISECONDS);
}
/** Sends requests and get's responses based on thread activity.
* Returns all the responses received once the thread activity has
* returned to the level it was before the requests.
* <p>
* This methods waits until the connection is closed or
* an idle period before returning the responses.
* @param requestsBuffer the requests
* @param idleFor The time the response stream must be idle for before returning
* @param units The units of idleFor
* @return the responses
* @throws Exception if the requests fail
*/
public ByteBuffer getResponses(ByteBuffer requestsBuffer,long idleFor,TimeUnit units) throws Exception
{
LOG.debug("getResponses");
Phaser phaser=_executor._phaser;
int phase = phaser.register(); // the corresponding arrival will be done by the acceptor thread when it takes
LocalEndPoint request = new LocalEndPoint();
request.setInput(requestsBuffer);
_connects.add(request);
phaser.awaitAdvance(phase);
return request.takeOutput();
LocalEndPoint endp = new LocalEndPoint();
endp.setInput(requestsBuffer);
_connects.add(endp);
endp.waitUntilClosedOrIdleFor(idleFor,units);
return endp.takeOutput();
}
/**
@ -86,8 +152,6 @@ public class LocalHttpConnector extends HttpConnector
*/
public LocalEndPoint executeRequest(String rawRequest)
{
Phaser phaser=_executor._phaser;
phaser.register(); // the corresponding arrival will be done by the acceptor thread when it takes
LocalEndPoint endp = new LocalEndPoint();
endp.setInput(BufferUtil.toBuffer(rawRequest,StringUtil.__UTF8_CHARSET));
_connects.add(endp);
@ -99,81 +163,21 @@ public class LocalHttpConnector extends HttpConnector
{
LOG.debug("accepting {}",acceptorID);
LocalEndPoint endp = _connects.take();
HttpConnection connection=new HttpConnection(this,endp,getServer());
endp.setAsyncConnection(connection);
Connection connection=getConnectionFactory().newConnection(LocalConnector.this,endp);
endp.setConnection(connection);
endp.onOpen();
connection.onOpen();
connectionOpened(connection);
_executor._phaser.arriveAndDeregister(); // arrive for the register done in getResponses
}
@Override
protected void doStart() throws Exception
{
super.doStart();
_executor=new LocalExecutor(findExecutor());
}
@Override
protected void doStop() throws Exception
{
super.doStop();
_executor=null;
}
@Override
public Executor findExecutor()
{
return _executor==null?super.findExecutor():_executor;
}
private class LocalExecutor implements Executor
{
private final Phaser _phaser=new Phaser()
{
@Override
protected boolean onAdvance(int phase, int registeredParties)
{
return false;
}
};
private final Executor _executor;
private LocalExecutor(Executor e)
{
_executor=e;
}
@Override
public void execute(final Runnable task)
{
_phaser.register();
LOG.debug("{} execute {} {}",this,task,_phaser);
_executor.execute(new Runnable()
{
@Override
public void run()
{
try
{
task.run();
}
finally
{
_phaser.arriveAndDeregister();
}
}
});
}
}
public class LocalEndPoint extends AsyncByteArrayEndPoint
public class LocalEndPoint extends ByteArrayEndPoint
{
private CountDownLatch _closed = new CountDownLatch(1);
public LocalEndPoint()
{
super(getScheduler(), LocalHttpConnector.this.getIdleTimeout());
super(getScheduler(), LocalConnector.this.getIdleTimeout());
setGrowOutput(true);
}
@ -192,7 +196,8 @@ public class LocalHttpConnector extends HttpConnector
super.close();
if (was_open)
{
connectionClosed(getAsyncConnection());
connectionClosed(getConnection());
getConnection().onClose();
onClose();
}
}
@ -231,5 +236,28 @@ public class LocalHttpConnector extends HttpConnector
}
}
}
public void waitUntilClosedOrIdleFor(long idleFor,TimeUnit units)
{
Thread.yield();
int size=getOutput().remaining();
while (isOpen())
{
try
{
if (!_closed.await(idleFor,units))
{
if (size==getOutput().remaining())
return;
size=getOutput().remaining();
}
}
catch(Exception e)
{
LOG.warn(e);
}
}
}
}
}

View File

@ -1358,7 +1358,7 @@ public class Request implements HttpServletRequest
@Override
public boolean isSecure()
{
return _channel.getHttpConnector().isConfidential(this);
return _channel.getHttpConfiguration().isConfidential(this);
}
/* ------------------------------------------------------------ */

View File

@ -16,17 +16,22 @@ package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.Channel;
import java.nio.channels.SelectionKey;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.SelectChannelEndPoint;
import org.eclipse.jetty.io.SelectorManager;
import org.eclipse.jetty.io.SelectorManager.ManagedSelector;
import org.eclipse.jetty.server.Connector.NetConnector;
import org.eclipse.jetty.util.annotation.Name;
import org.eclipse.jetty.util.ssl.SslContextFactory;
/**
* Selecting NIO connector.
@ -51,27 +56,85 @@ import org.eclipse.jetty.server.Connector.NetConnector;
* associated object of the Continuation instance.
* </p>
*/
public class SelectChannelConnector extends HttpConnector implements NetConnector
public class SelectChannelConnector extends AbstractNetConnector
{
private final SelectorManager _manager;
protected ServerSocketChannel _acceptChannel;
protected boolean _inheritChannel;
private int _localPort=-1;
/**
* Constructor.
*
*/
public SelectChannelConnector()
/* ------------------------------------------------------------ */
public SelectChannelConnector(Server server)
{
this(Math.max(1,(Runtime.getRuntime().availableProcessors())/4),
Math.max(1,(Runtime.getRuntime().availableProcessors())/4));
this(server,null,null,null,null,0,0);
}
/* ------------------------------------------------------------ */
public SelectChannelConnector(Server server, boolean ssl)
{
this(server,new ConnectionFactory(null,ssl));
manage(getConnectionFactory());
}
/* ------------------------------------------------------------ */
public SelectChannelConnector(Server server, SslContextFactory sslContextFactory)
{
this(server,new ConnectionFactory(sslContextFactory,sslContextFactory!=null));
manage(getConnectionFactory());
}
public SelectChannelConnector(int acceptors, int selectors)
/* ------------------------------------------------------------ */
public SelectChannelConnector(Server server, ConnectionFactory connectionFactory)
{
super(acceptors);
_manager=new ConnectorSelectorManager(selectors);
this(server,connectionFactory,null,null,null,0,0);
}
/* ------------------------------------------------------------ */
/**
* @param server The server this connector will be added to. Must not be null.
* @param executor An executor for this connector or null to use the servers executor
* @param scheduler A scheduler for this connector or null to use the servers scheduler
* @param pool A buffer pool for this connector or null to use a default {@link ByteBufferPool}
* @param acceptors the number of acceptor threads to use, or 0 for a default value.
*/
public SelectChannelConnector(
@Name("server") Server server,
@Name("connectionFactory") ConnectionFactory connectionFactory,
@Name("executor") Executor executor,
@Name("scheduler") ScheduledExecutorService scheduler,
@Name("bufferPool") ByteBufferPool pool,
@Name("acceptors") int acceptors,
@Name("selectors") int selectors)
{
super(server,connectionFactory,executor,scheduler,pool,acceptors);
_manager=new ConnectorSelectorManager(selectors!=0?selectors:Math.max(1,(Runtime.getRuntime().availableProcessors())/4));
addBean(_manager,true);
// TODO yuck
if (getConnectionFactory().getSslContextFactory()!=null)
setSoLingerTime(30000);
}
public boolean isInheritChannel()
{
return _inheritChannel;
}
/**
* If true, the connector first tries to inherit from a channel provided by the system.
* If there is no inherited channel available, or if the inherited channel provided not usable,
* then it will fall back upon normal ServerSocketChannel creation.
* <p>
* Use it with xinetd/inetd, to launch an instance of Jetty on demand. The port
* used to access pages on the Jetty instance is the same as the port used to
* launch Jetty.
*
*/
public void setInheritChannel(boolean inheritChannel)
{
_inheritChannel = inheritChannel;
}
@Override
@ -109,13 +172,6 @@ public class SelectChannelConnector extends HttpConnector implements NetConnecto
}
}
@Override
public void customize(Request request) throws IOException
{
request.setTimeStamp(System.currentTimeMillis());
super.customize(request);
}
public SelectorManager getSelectorManager()
{
return _manager;
@ -143,25 +199,39 @@ public class SelectChannelConnector extends HttpConnector implements NetConnecto
{
if (_acceptChannel == null)
{
// Create a new server socket
_acceptChannel = ServerSocketChannel.open();
// Set to blocking mode
if (_inheritChannel)
{
Channel channel = System.inheritedChannel();
if ( channel instanceof ServerSocketChannel )
_acceptChannel = (ServerSocketChannel)channel;
else
LOG.warn("Unable to use System.inheritedChannel() [" +channel+ "]. Trying a new ServerSocketChannel at " + getHost() + ":" + getPort());
}
if (_acceptChannel == null)
{
// Create a new server socket
_acceptChannel = ServerSocketChannel.open();
// Bind the server socket to the local host and port
_acceptChannel.socket().setReuseAddress(getReuseAddress());
InetSocketAddress addr = getHost()==null?new InetSocketAddress(getPort()):new InetSocketAddress(getHost(),getPort());
_acceptChannel.socket().bind(addr,getAcceptQueueSize());
_localPort=_acceptChannel.socket().getLocalPort();
if (_localPort<=0)
throw new IOException("Server channel not bound");
addBean(_acceptChannel);
}
_acceptChannel.configureBlocking(true);
// Bind the server socket to the local host and port
_acceptChannel.socket().setReuseAddress(getReuseAddress());
InetSocketAddress addr = getHost()==null?new InetSocketAddress(getPort()):new InetSocketAddress(getHost(),getPort());
_acceptChannel.socket().bind(addr,getAcceptQueueSize());
_localPort=_acceptChannel.socket().getLocalPort();
if (_localPort<=0)
throw new IOException("Server channel not bound");
addBean(_acceptChannel);
}
}
}
/*
* @see org.eclipse.jetty.server.server.AbstractConnector#doStart()
*/
@ -176,17 +246,11 @@ public class SelectChannelConnector extends HttpConnector implements NetConnecto
return new SelectChannelEndPoint(channel,selectSet,key, getScheduler(), getIdleTimeout());
}
protected void endPointClosed(AsyncEndPoint endpoint)
protected void endPointClosed(EndPoint endpoint)
{
connectionClosed(endpoint.getAsyncConnection());
connectionClosed(endpoint.getConnection());
}
protected AsyncConnection newConnection(SocketChannel channel,final AsyncEndPoint endpoint)
{
return new HttpConnection(SelectChannelConnector.this,endpoint,getServer());
}
/* ------------------------------------------------------------ */
private final class ConnectorSelectorManager extends SelectorManager
{
@ -198,29 +262,29 @@ public class SelectChannelConnector extends HttpConnector implements NetConnecto
@Override
protected void execute(Runnable task)
{
findExecutor().execute(task);
getExecutor().execute(task);
}
@Override
protected void endPointClosed(AsyncEndPoint endpoint)
protected void endPointClosed(EndPoint endpoint)
{
SelectChannelConnector.this.connectionClosed(endpoint.getAsyncConnection());
SelectChannelConnector.this.connectionClosed(endpoint.getConnection());
super.endPointClosed(endpoint);
}
@Override
protected void endPointOpened(AsyncEndPoint endpoint)
protected void endPointOpened(EndPoint endpoint)
{
// TODO handle max connections and low resources
super.endPointOpened(endpoint);
SelectChannelConnector.this.connectionOpened(endpoint.getAsyncConnection());
SelectChannelConnector.this.connectionOpened(endpoint.getConnection());
}
@Override
public void connectionUpgraded(AsyncEndPoint endpoint, AsyncConnection oldConnection)
public void connectionUpgraded(EndPoint endpoint, Connection oldConnection)
{
super.connectionUpgraded(endpoint, oldConnection);
SelectChannelConnector.this.connectionUpgraded(oldConnection, endpoint.getAsyncConnection());
SelectChannelConnector.this.connectionUpgraded(oldConnection, endpoint.getConnection());
}
@Override
@ -230,9 +294,9 @@ public class SelectChannelConnector extends HttpConnector implements NetConnecto
}
@Override
public AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint, Object attachment)
public Connection newConnection(SocketChannel channel, EndPoint endpoint, Object attachment) throws IOException
{
return SelectChannelConnector.this.newConnection(channel, endpoint);
return getConnectionFactory().newConnection(SelectChannelConnector.this,endpoint);
}
}
}

View File

@ -66,7 +66,7 @@ public class Server extends HandlerWrapper implements Attributes
private final Container _container=new Container();
private final AttributesMap _attributes = new AttributesMap();
private ThreadPool _threadPool;
private final ThreadPool _threadPool;
private Connector[] _connectors;
private SessionIdManager _sessionIdManager;
private boolean _sendServerVersion = true; //send Server: header
@ -81,7 +81,7 @@ public class Server extends HandlerWrapper implements Attributes
/* ------------------------------------------------------------ */
public Server()
{
setServer(this);
this((ThreadPool)null);
}
/* ------------------------------------------------------------ */
@ -90,9 +90,8 @@ public class Server extends HandlerWrapper implements Attributes
*/
public Server(int port)
{
setServer(this);
SelectChannelConnector connector=new SelectChannelConnector();
this((ThreadPool)null);
SelectChannelConnector connector=new SelectChannelConnector(this);
connector.setPort(port);
setConnectors(new Connector[]{connector});
}
@ -103,15 +102,23 @@ public class Server extends HandlerWrapper implements Attributes
*/
public Server(InetSocketAddress addr)
{
setServer(this);
SelectChannelConnector connector=new SelectChannelConnector();
this((ThreadPool)null);
SelectChannelConnector connector=new SelectChannelConnector(this);
connector.setHost(addr.getHostName());
connector.setPort(addr.getPort());
setConnectors(new Connector[]{connector});
}
/* ------------------------------------------------------------ */
public Server(ThreadPool pool)
{
_threadPool=pool!=null?pool:new QueuedThreadPool();
addBean(_threadPool,pool==null);
setServer(this);
}
/* ------------------------------------------------------------ */
public static String getVersion()
{
@ -189,9 +196,8 @@ public class Server extends HandlerWrapper implements Attributes
{
for (int i=0;i<connectors.length;i++)
{
// TODO review
if (connectors[i] instanceof AbstractConnector)
((AbstractConnector)connectors[i]).setServer(this);
if (connectors[i].getServer()!=this)
throw new IllegalArgumentException();
}
}
@ -208,20 +214,6 @@ public class Server extends HandlerWrapper implements Attributes
return _threadPool;
}
/* ------------------------------------------------------------ */
/**
* @param threadPool The threadPool to set.
*/
public void setThreadPool(ThreadPool threadPool)
{
if (_threadPool!=null)
removeBean(_threadPool);
_container.update(this, _threadPool, threadPool, "threadpool",false);
_threadPool = threadPool;
if (_threadPool!=null)
addBean(_threadPool);
}
/**
* @return true if {@link #dumpStdErr()} is called after starting
*/
@ -267,9 +259,6 @@ public class Server extends HandlerWrapper implements Attributes
HttpGenerator.setServerVersion(__version);
MultiException mex=new MultiException();
if (_threadPool==null)
setThreadPool(new QueuedThreadPool());
try
{
super.doStart();

View File

@ -904,7 +904,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
// Check the connector
if (_connectors != null && _connectors.size() > 0)
{
String connector = HttpChannel.getCurrentHttpChannel().getHttpConnector().getName();
String connector = HttpChannel.getCurrentHttpChannel().getConnector().getName();
if (connector == null || !_connectors.contains(connector))
return false;
}

View File

@ -1,71 +0,0 @@
// ========================================================================
// Copyright (c) 2008-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.server.nio;
import java.io.IOException;
import java.nio.channels.Channel;
import java.nio.channels.ServerSocketChannel;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/**
* An implementation of the SelectChannelConnector which first tries to
* inherit from a channel provided by the system. If there is no inherited
* channel available, or if the inherited channel provided not usable, then
* it will fall back upon normal ServerSocketChannel creation.
* <p>
* Note that System.inheritedChannel() is only available from Java 1.5 onwards.
* Trying to use this class under Java 1.4 will be the same as using a normal
* SelectChannelConnector.
* <p>
* Use it with xinetd/inetd, to launch an instance of Jetty on demand. The port
* used to access pages on the Jetty instance is the same as the port used to
* launch Jetty.
*
* @author athena
*/
public class InheritedChannelConnector extends SelectChannelConnector
{
private static final Logger LOG = Log.getLogger(InheritedChannelConnector.class);
/* ------------------------------------------------------------ */
@Override
public void open() throws IOException
{
synchronized(this)
{
try
{
Channel channel = System.inheritedChannel();
if ( channel instanceof ServerSocketChannel )
_acceptChannel = (ServerSocketChannel)channel;
else
LOG.warn("Unable to use System.inheritedChannel() [" +channel+ "]. Trying a new ServerSocketChannel at " + getHost() + ":" + getPort());
if ( _acceptChannel != null )
_acceptChannel.configureBlocking(true);
}
catch(NoSuchMethodError e)
{
LOG.warn("Need at least Java 5 to use socket inherited from xinetd/inetd.");
}
if (_acceptChannel == null)
super.open();
}
}
}

View File

@ -19,13 +19,18 @@ import java.nio.channels.SocketChannel;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ByteBufferPool;
import org.eclipse.jetty.io.NetworkTrafficListener;
import org.eclipse.jetty.io.NetworkTrafficSelectChannelEndPoint;
import org.eclipse.jetty.io.SelectChannelEndPoint;
import org.eclipse.jetty.io.SelectorManager;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.ssl.SslContextFactory;
/**
* <p>A specialized version of {@link SelectChannelConnector} that supports {@link NetworkTrafficListener}s.</p>
@ -36,6 +41,12 @@ public class NetworkTrafficSelectChannelConnector extends SelectChannelConnector
{
private final List<NetworkTrafficListener> listeners = new CopyOnWriteArrayList<NetworkTrafficListener>();
public NetworkTrafficSelectChannelConnector(Server server)
{
super(server);
}
/**
* @param listener the listener to add
*/
@ -61,7 +72,7 @@ public class NetworkTrafficSelectChannelConnector extends SelectChannelConnector
}
@Override
protected void endPointClosed(AsyncEndPoint endpoint)
protected void endPointClosed(EndPoint endpoint)
{
super.endPointClosed(endpoint);
((NetworkTrafficSelectChannelEndPoint)endpoint).notifyClosed();

View File

@ -1,8 +0,0 @@
package org.eclipse.jetty.server.nio;
/**
* @deprecated Use {@link org.eclipse.jetty.server.SelectChannelConnector}
*/
public class SelectChannelConnector extends org.eclipse.jetty.server.SelectChannelConnector
{
}

View File

@ -21,7 +21,6 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManagerFactory;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
@ -29,7 +28,8 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
/** The interface for SSL connectors and their configuration methods.
*
*/
public interface SslConnector extends Connector.NetConnector
@Deprecated
interface SslConnector
{
@Deprecated
public static final String DEFAULT_KEYSTORE_ALGORITHM=(Security.getProperty("ssl.KeyManagerFactory.algorithm")==null?"SunX509":Security.getProperty("ssl.KeyManagerFactory.algorithm"));

View File

@ -13,607 +13,21 @@
package org.eclipse.jetty.server.ssl;
import java.io.IOException;
import java.nio.channels.SocketChannel;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSession;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.RuntimeIOException;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.ssl.SslContextFactory;
/* ------------------------------------------------------------ */
/**
* SslSelectChannelConnector.
*
* @deprecated use SelectChannelConnector with {@link SslContextFactory}
* @org.apache.xbean.XBean element="sslConnector" description="Creates an NIO ssl connector"
*/
public class SslSelectChannelConnector extends SelectChannelConnector implements SslConnector
public class SslSelectChannelConnector extends SelectChannelConnector
{
private final SslContextFactory _sslContextFactory;
/* ------------------------------------------------------------ */
public SslSelectChannelConnector()
public SslSelectChannelConnector(Server server)
{
this(new SslContextFactory(SslContextFactory.DEFAULT_KEYSTORE_PATH));
setSoLingerTime(30000);
}
/* ------------------------------------------------------------ */
/** Construct with explicit SslContextFactory.
* The SslContextFactory passed is added via {@link #addBean(Object)} so that
* it's lifecycle may be managed with {@link AggregateLifeCycle}.
* @param sslContextFactory
*/
public SslSelectChannelConnector(SslContextFactory sslContextFactory)
{
_sslContextFactory = sslContextFactory;
addBean(_sslContextFactory);
setSoLingerTime(30000);
}
/* ------------------------------------------------------------ */
/**
* Allow the Listener a chance to customise the request. before the server
* does its stuff. <br>
* This allows the required attributes to be set for SSL requests. <br>
* The requirements of the Servlet specs are:
* <ul>
* <li> an attribute named "javax.servlet.request.ssl_session_id" of type
* String (since Servlet Spec 3.0).</li>
* <li> an attribute named "javax.servlet.request.cipher_suite" of type
* String.</li>
* <li> an attribute named "javax.servlet.request.key_size" of type Integer.</li>
* <li> an attribute named "javax.servlet.request.X509Certificate" of type
* java.security.cert.X509Certificate[]. This is an array of objects of type
* X509Certificate, the order of this array is defined as being in ascending
* order of trust. The first certificate in the chain is the one set by the
* client, the next is the one used to authenticate the first, and so on.
* </li>
* </ul>
*
* @param request
* HttpRequest to be customised.
*/
@Override
public void customize(Request request) throws IOException
{
request.setScheme(HttpScheme.HTTPS.asString());
super.customize(request);
SslConnection.DecryptedEndPoint ssl_endp = (SslConnection.DecryptedEndPoint)request.getHttpChannel().getEndPoint();
SslConnection sslConnection = ssl_endp.getSslConnection();
SSLEngine sslEngine=sslConnection.getSSLEngine();
SslCertificates.customize(sslEngine,request);
}
/* ------------------------------------------------------------ */
/**
* @return True if SSL re-negotiation is allowed (default false)
* @deprecated
*/
@Deprecated
public boolean isAllowRenegotiate()
{
return _sslContextFactory.isAllowRenegotiate();
}
/* ------------------------------------------------------------ */
/**
* Set if SSL re-negotiation is allowed. CVE-2009-3555 discovered
* a vulnerability in SSL/TLS with re-negotiation. If your JVM
* does not have CVE-2009-3555 fixed, then re-negotiation should
* not be allowed. CVE-2009-3555 was fixed in Sun java 1.6 with a ban
* of renegotiate in u19 and with RFC5746 in u22.
* @param allowRenegotiate true if re-negotiation is allowed (default false)
* @deprecated
*/
@Deprecated
public void setAllowRenegotiate(boolean allowRenegotiate)
{
_sslContextFactory.setAllowRenegotiate(allowRenegotiate);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites()
* @deprecated
*/
@Deprecated
public String[] getExcludeCipherSuites()
{
return _sslContextFactory.getExcludeCipherSuites();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[])
* @deprecated
*/
@Deprecated
public void setExcludeCipherSuites(String[] cipherSuites)
{
_sslContextFactory.setExcludeCipherSuites(cipherSuites);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getExcludeCipherSuites()
* @deprecated
*/
@Deprecated
public String[] getIncludeCipherSuites()
{
return _sslContextFactory.getIncludeCipherSuites();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setExcludeCipherSuites(java.lang.String[])
* @deprecated
*/
@Deprecated
public void setIncludeCipherSuites(String[] cipherSuites)
{
_sslContextFactory.setIncludeCipherSuites(cipherSuites);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setPassword(java.lang.String)
* @deprecated
*/
@Deprecated
public void setPassword(String password)
{
_sslContextFactory.setKeyStorePassword(password);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setTrustPassword(java.lang.String)
* @deprecated
*/
@Deprecated
public void setTrustPassword(String password)
{
_sslContextFactory.setTrustStorePassword(password);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setKeyPassword(java.lang.String)
* @deprecated
*/
@Deprecated
public void setKeyPassword(String password)
{
_sslContextFactory.setKeyManagerPassword(password);
}
/* ------------------------------------------------------------ */
/**
* Unsupported.
*
* TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past)
* @deprecated
*/
@Deprecated
public String getAlgorithm()
{
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
/**
* Unsupported.
*
* TODO: we should remove this as it is no longer an overridden method from SslConnector (like it was in the past)
* @deprecated
*/
@Deprecated
public void setAlgorithm(String algorithm)
{
throw new UnsupportedOperationException();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getProtocol()
* @deprecated
*/
@Deprecated
public String getProtocol()
{
return _sslContextFactory.getProtocol();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setProtocol(java.lang.String)
* @deprecated
*/
@Deprecated
public void setProtocol(String protocol)
{
_sslContextFactory.setProtocol(protocol);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setKeystore(java.lang.String)
* @deprecated
*/
@Deprecated
public void setKeystore(String keystore)
{
_sslContextFactory.setKeyStorePath(keystore);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getKeystore()
* @deprecated
*/
@Deprecated
public String getKeystore()
{
return _sslContextFactory.getKeyStorePath();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getKeystoreType()
* @deprecated
*/
@Deprecated
public String getKeystoreType()
{
return _sslContextFactory.getKeyStoreType();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getNeedClientAuth()
* @deprecated
*/
@Deprecated
public boolean getNeedClientAuth()
{
return _sslContextFactory.getNeedClientAuth();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getWantClientAuth()
* @deprecated
*/
@Deprecated
public boolean getWantClientAuth()
{
return _sslContextFactory.getWantClientAuth();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setNeedClientAuth(boolean)
* @deprecated
*/
@Deprecated
public void setNeedClientAuth(boolean needClientAuth)
{
_sslContextFactory.setNeedClientAuth(needClientAuth);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setWantClientAuth(boolean)
* @deprecated
*/
@Deprecated
public void setWantClientAuth(boolean wantClientAuth)
{
_sslContextFactory.setWantClientAuth(wantClientAuth);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setKeystoreType(java.lang.String)
* @deprecated
*/
@Deprecated
public void setKeystoreType(String keystoreType)
{
_sslContextFactory.setKeyStoreType(keystoreType);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getProvider()
* @deprecated
*/
@Deprecated
public String getProvider()
{
return _sslContextFactory.getProvider();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getSecureRandomAlgorithm()
* @deprecated
*/
@Deprecated
public String getSecureRandomAlgorithm()
{
return _sslContextFactory.getSecureRandomAlgorithm();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getSslKeyManagerFactoryAlgorithm()
* @deprecated
*/
@Deprecated
public String getSslKeyManagerFactoryAlgorithm()
{
return _sslContextFactory.getSslKeyManagerFactoryAlgorithm();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getSslTrustManagerFactoryAlgorithm()
* @deprecated
*/
@Deprecated
public String getSslTrustManagerFactoryAlgorithm()
{
return _sslContextFactory.getTrustManagerFactoryAlgorithm();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getTruststore()
* @deprecated
*/
@Deprecated
public String getTruststore()
{
return _sslContextFactory.getTrustStore();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getTruststoreType()
* @deprecated
*/
@Deprecated
public String getTruststoreType()
{
return _sslContextFactory.getTrustStoreType();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setProvider(java.lang.String)
* @deprecated
*/
@Deprecated
public void setProvider(String provider)
{
_sslContextFactory.setProvider(provider);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setSecureRandomAlgorithm(java.lang.String)
* @deprecated
*/
@Deprecated
public void setSecureRandomAlgorithm(String algorithm)
{
_sslContextFactory.setSecureRandomAlgorithm(algorithm);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setSslKeyManagerFactoryAlgorithm(java.lang.String)
* @deprecated
*/
@Deprecated
public void setSslKeyManagerFactoryAlgorithm(String algorithm)
{
_sslContextFactory.setSslKeyManagerFactoryAlgorithm(algorithm);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setSslTrustManagerFactoryAlgorithm(java.lang.String)
* @deprecated
*/
@Deprecated
public void setSslTrustManagerFactoryAlgorithm(String algorithm)
{
_sslContextFactory.setTrustManagerFactoryAlgorithm(algorithm);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setTruststore(java.lang.String)
* @deprecated
*/
@Deprecated
public void setTruststore(String truststore)
{
_sslContextFactory.setTrustStore(truststore);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setTruststoreType(java.lang.String)
* @deprecated
*/
@Deprecated
public void setTruststoreType(String truststoreType)
{
_sslContextFactory.setTrustStoreType(truststoreType);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext)
* @deprecated
*/
@Deprecated
public void setSslContext(SSLContext sslContext)
{
_sslContextFactory.setSslContext(sslContext);
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#setSslContext(javax.net.ssl.SSLContext)
* @deprecated
*/
@Deprecated
public SSLContext getSslContext()
{
return _sslContextFactory.getSslContext();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.ssl.SslConnector#getSslContextFactory()
*/
public SslContextFactory getSslContextFactory()
{
return _sslContextFactory;
}
/* ------------------------------------------------------------ */
/**
* By default, we're confidential, given we speak SSL. But, if we've been
* told about an confidential port, and said port is not our port, then
* we're not. This allows separation of listeners providing INTEGRAL versus
* CONFIDENTIAL constraints, such as one SSL listener configured to require
* client certs providing CONFIDENTIAL, whereas another SSL listener not
* requiring client certs providing mere INTEGRAL constraints.
*/
@Override
public boolean isConfidential(Request request)
{
final int confidentialPort=getConfidentialPort();
return confidentialPort==0||confidentialPort==request.getServerPort();
}
/* ------------------------------------------------------------ */
/**
* By default, we're integral, given we speak SSL. But, if we've been told
* about an integral port, and said port is not our port, then we're not.
* This allows separation of listeners providing INTEGRAL versus
* CONFIDENTIAL constraints, such as one SSL listener configured to require
* client certs providing CONFIDENTIAL, whereas another SSL listener not
* requiring client certs providing mere INTEGRAL constraints.
*/
@Override
public boolean isIntegral(Request request)
{
final int integralPort=getIntegralPort();
return integralPort==0||integralPort==request.getServerPort();
}
/* ------------------------------------------------------------------------------- */
@Override
protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint)
{
try
{
SSLEngine engine = createSSLEngine(channel);
SslConnection connection = newSslConnection(endpoint, engine);
AsyncConnection delegate = newPlainConnection(channel, connection.getSslEndPoint());
connection.getSslEndPoint().setAsyncConnection(delegate);
getSelectorManager().connectionOpened(delegate);
return connection;
}
catch (IOException e)
{
throw new RuntimeIOException(e);
}
}
protected AsyncConnection newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint)
{
return super.newConnection(channel, endPoint);
}
protected SslConnection newSslConnection(AsyncEndPoint endpoint, SSLEngine engine)
{
return new SslConnection(getByteBufferPool(), findExecutor(), endpoint, engine);
}
/* ------------------------------------------------------------ */
/**
* @param channel A channel which if passed is used as to extract remote
* host and port for the purposes of SSL session caching
* @return A SSLEngine for a new or cached SSL Session
* @throws IOException if the SSLEngine cannot be created
*/
protected SSLEngine createSSLEngine(SocketChannel channel) throws IOException
{
SSLEngine engine;
if (channel != null)
{
String peerHost = channel.socket().getInetAddress().getHostAddress();
int peerPort = channel.socket().getPort();
engine = _sslContextFactory.newSslEngine(peerHost, peerPort);
}
else
{
engine = _sslContextFactory.newSslEngine();
}
engine.setUseClientMode(false);
return engine;
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.SelectChannelConnector#doStart()
*/
@Override
protected void doStart() throws Exception
{
_sslContextFactory.checkKeyStore();
_sslContextFactory.start();
SSLEngine sslEngine = _sslContextFactory.newSslEngine();
sslEngine.setUseClientMode(false);
SSLSession sslSession = sslEngine.getSession();
if (getRequestHeaderSize()<sslSession.getApplicationBufferSize())
setRequestHeaderSize(sslSession.getApplicationBufferSize());
if (getRequestBufferSize()<sslSession.getApplicationBufferSize())
setRequestBufferSize(sslSession.getApplicationBufferSize());
super.doStart();
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.server.SelectChannelConnector#doStop()
*/
@Override
protected void doStop() throws Exception
{
super.doStop();
super(server,true);
}
}

View File

@ -52,7 +52,7 @@ public class AsyncRequestReadTest
public static void startServer() throws Exception
{
server = new Server();
connector = new SelectChannelConnector();
connector = new SelectChannelConnector(server);
connector.setIdleTimeout(10000);
server.addConnector(connector);
server.setHandler(new EmptyHandler());

View File

@ -46,13 +46,13 @@ public class AsyncStressTest
{
private static final Logger LOG = Log.getLogger(AsyncStressTest.class);
protected Server _server = new Server();
protected QueuedThreadPool _threads=new QueuedThreadPool();
protected Server _server = new Server(_threads);
protected SuspendHandler _handler = new SuspendHandler();
protected SelectChannelConnector _connector;
protected InetAddress _addr;
protected int _port;
protected Random _random = new Random();
protected QueuedThreadPool _threads=new QueuedThreadPool();
private final static String[][] __paths =
{
{"/path","NORMAL"},
@ -66,9 +66,9 @@ public class AsyncStressTest
@Before
public void init() throws Exception
{
_server.manage(_threads);
_threads.setMaxThreads(50);
_server.setThreadPool(_threads);
_connector = new SelectChannelConnector();
_connector = new SelectChannelConnector(_server);
_connector.setIdleTimeout(120000);
_server.setConnectors(new Connector[]{ _connector });
_server.setHandler(_handler);

View File

@ -9,7 +9,7 @@ public class ChannelHttpServer
System.setProperty("org.eclipse.jetty.LEVEL","DEBUG");
Log.getRootLogger().setDebugEnabled(true);
Server server = new Server();
SelectChannelConnector connector = new SelectChannelConnector();
SelectChannelConnector connector = new SelectChannelConnector(server);
connector.setPort(8080);
server.addConnector(connector);
server.setHandler(new DumpHandler());

View File

@ -93,10 +93,10 @@ public class CheckReverseProxyHeadersTest
private void testRequest(String headers, RequestValidator requestValidator) throws Exception
{
Server server = new Server();
LocalHttpConnector connector = new LocalHttpConnector();
LocalConnector connector = new LocalConnector(server);
// Activate reverse proxy headers checking
connector.setForwarded(true);
connector.getConnectionFactory().getHttpConfig().setForwarded(true);
server.setConnectors(new Connector[] {connector});
ValidationHandler validationHandler = new ValidationHandler(requestValidator);

View File

@ -1,16 +1,13 @@
//========================================================================
//Copyright (c) Webtide LLC
//Copyright 2011-2012 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.apache.org/licenses/LICENSE-2.0.txt
//
//You may elect to redistribute this code under either of these licenses.
//========================================================================

View File

@ -150,7 +150,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
// Get the server side endpoint
EndPoint endp = endpoint.exchange(null,10,TimeUnit.SECONDS);
if (endp instanceof SslConnection.DecryptedEndPoint)
endp=((SslConnection.DecryptedEndPoint)endp).getAsyncConnection().getEndPoint();
endp=((SslConnection.DecryptedEndPoint)endp).getConnection().getEndPoint();
// read the response
String result=IO.toString(is);
@ -223,7 +223,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
// Get the server side endpoint
EndPoint endp = endpoint.exchange(null,10,TimeUnit.SECONDS);
if (endp instanceof SslConnection.DecryptedEndPoint)
endp=((SslConnection.DecryptedEndPoint)endp).getAsyncConnection().getEndPoint();
endp=((SslConnection.DecryptedEndPoint)endp).getConnection().getEndPoint();
// read the response
String result=IO.toString(is);

View File

@ -27,6 +27,7 @@ import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
@ -52,16 +53,16 @@ public class HttpConnectionTest
private static final Logger LOG = Log.getLogger(HttpConnectionTest.class);
private Server server;
private LocalHttpConnector connector;
private LocalConnector connector;
@Before
public void init() throws Exception
{
server = new Server();
connector = new LocalHttpConnector();
connector = new LocalConnector(server);
server.addConnector(connector);
connector.setRequestHeaderSize(1024);
connector.setResponseHeaderSize(1024);
connector.getConnectionFactory().getHttpConfig().setRequestHeaderSize(1024);
connector.getConnectionFactory().getHttpConfig().setResponseHeaderSize(1024);
server.setHandler(new DumpHandler());
server.start();
}
@ -87,6 +88,7 @@ public class HttpConnectionTest
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"Connection: close\n"+
"\015\012"+
"5;\015\012"+
"12345\015\012"+
@ -100,6 +102,7 @@ public class HttpConnectionTest
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"Connection: close\n"+
"\015\012"+
"5;\015\012"+
"ABCDE\015\012"+
@ -124,6 +127,7 @@ public class HttpConnectionTest
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"Connection: close\n"+
"\015\012"+
"0\015\012\015\012");
@ -137,10 +141,12 @@ public class HttpConnectionTest
{
String responsePOST=connector.getResponses("POST /R1 HTTP/1.1\015\012"+
"Host: localhost\015\012"+
"Connection: close\015\012"+
"\015\012");
String responseHEAD=connector.getResponses("HEAD /R1 HTTP/1.1\015\012"+
"Host: localhost\015\012"+
"Connection: close\015\012"+
"\015\012");
assertThat(responsePOST,startsWith(responseHEAD.substring(0,responseHEAD.length()-2)));
@ -148,6 +154,7 @@ public class HttpConnectionTest
responsePOST=connector.getResponses("POST /R1 HTTP/1.1\015\012"+
"Host: localhost\015\012"+
"Connection: close\015\012"+
"\015\012");
assertThat(responsePOST,startsWith(responseHEAD.substring(0,responseHEAD.length()-2)));
@ -162,16 +169,19 @@ public class HttpConnectionTest
response=connector.getResponses("GET http://localhost:EXPECTED_NUMBER_FORMAT_EXCEPTION/ HTTP/1.1\n"+
"Host: localhost\n"+
"Connection: close\015\012"+
"\015\012");
checkContains(response,0,"HTTP/1.1 400");
response=connector.getResponses("GET /bad/encoding%1 HTTP/1.1\n"+
"Host: localhost\n"+
"Connection: close\n"+
"\015\012");
checkContains(response,0,"HTTP/1.1 400");
response=connector.getResponses("GET % HTTP/1.1\n"+
"Host: localhost\n"+
"Connection: close\n"+
"\015\012");
checkContains(response,0,"HTTP/1.1 400");
}
@ -180,21 +190,22 @@ public class HttpConnectionTest
public void testAutoFlush() throws Exception
{
String response=null;
int offset=0;
int offset=0;
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"\015\012"+
"5;\015\012"+
"12345\015\012"+
"0;\015\012\015\012");
offset = checkContains(response,offset,"HTTP/1.1 200");
checkNotContained(response,offset,"IgnoreMe");
offset = checkContains(response,offset,"/R1");
offset = checkContains(response,offset,"12345");
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain\n"+
"Connection: close\n"+
"\015\012"+
"5;\015\012"+
"12345\015\012"+
"0;\015\012\015\012");
offset = checkContains(response,offset,"HTTP/1.1 200");
checkNotContained(response,offset,"IgnoreMe");
offset = checkContains(response,offset,"/R1");
offset = checkContains(response,offset,"12345");
}
@Test
@ -211,6 +222,7 @@ public class HttpConnectionTest
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain; charset=utf-8\n"+
"Connection: close\n"+
"\015\012"+
"5;\015\012"+
"12345\015\012"+
@ -225,6 +237,7 @@ public class HttpConnectionTest
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain; charset = iso-8859-1 ; other=value\n"+
"Connection: close\n"+
"\015\012"+
"5;\015\012"+
"12345\015\012"+
@ -239,6 +252,7 @@ public class HttpConnectionTest
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain; charset=unknown\n"+
"Connection: close\n"+
"\015\012"+
"5;\015\012"+
"12345\015\012"+
@ -281,6 +295,7 @@ public class HttpConnectionTest
"Host: localhost\n"+
"Content-Type: text/plain; charset=utf-8\n"+
"Content-Length: 10\n"+
"Connection: close\n"+
"\n"+
"abcdefghij\n";
@ -527,6 +542,7 @@ public class HttpConnectionTest
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain; charset=utf-8\n"+
"Connection: close\n"+
"\015\012"+
"5;\015\012"+
"12345\015\012"+
@ -543,6 +559,7 @@ public class HttpConnectionTest
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain; charset=utf-8\n"+
"Connection: close\n"+
"\015\012"+
"5;\015\012"+
"12345\015\012"+
@ -554,6 +571,7 @@ public class HttpConnectionTest
"Host: localhost\n"+
"Transfer-Encoding: chunked\n"+
"Content-Type: text/plain; charset=utf-8\n"+
"Connection: close\n"+
"\015\012"+
"5;\015\012"+
"12345\015\012"+
@ -585,7 +603,7 @@ public class HttpConnectionTest
response=connector.getResponses("CONNECT www.webtide.com:8080 HTTP/1.1\n"+
"Host: myproxy:8888\015\012"+
"\015\012");
"\015\012",200,TimeUnit.MILLISECONDS);
checkContains(response,offset,"HTTP/1.1 200");
}

View File

@ -31,6 +31,7 @@ import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.toolchain.test.Stress;
import org.eclipse.jetty.util.IO;
import org.junit.AfterClass;
import org.junit.BeforeClass;
public class HttpServerTestFixture
@ -52,9 +53,14 @@ public class HttpServerTestFixture
return socket;
}
protected static void startServer(Connector.NetConnector connector) throws Exception
@BeforeClass
public static void before()
{
_server = new Server();
}
protected static void startServer(Connector.NetConnector connector) throws Exception
{
_connector = connector;
_server.addConnector(_connector);
_server.setHandler(new HandlerWrapper());

View File

@ -12,6 +12,8 @@ package org.eclipse.jetty.server;
//You may elect to redistribute this code under either of these licenses.
//========================================================================
import static org.junit.Assert.assertEquals;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.concurrent.ScheduledExecutorService;
@ -24,8 +26,6 @@ import org.eclipse.jetty.util.Utf8StringBuilder;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class HttpWriterTest
{
private HttpWriter _writer;
@ -39,7 +39,7 @@ public class HttpWriterTest
HttpChannel channel = new HttpChannel(null,null,null)
{
@Override
public HttpConnector getHttpConnector()
public HttpConfiguration getHttpConfiguration()
{
return null;
}
@ -98,6 +98,12 @@ public class HttpWriterTest
{
return null;
}
@Override
public Connector getConnector()
{
return null;
}
};

View File

@ -59,7 +59,7 @@ public class LocalAsyncContextTest
protected Connector initConnector()
{
return new LocalHttpConnector();
return new LocalConnector(_server);
}
@After
@ -247,8 +247,8 @@ public class LocalAsyncContextTest
protected String getResponse(String request) throws Exception
{
LocalHttpConnector connector=(LocalHttpConnector)_connector;
LocalHttpConnector.LocalEndPoint endp = connector.executeRequest(request);
LocalConnector connector=(LocalConnector)_connector;
LocalConnector.LocalEndPoint endp = connector.executeRequest(request);
endp.waitUntilClosed();
return endp.takeOutputString();
}

View File

@ -10,13 +10,13 @@ import org.junit.Test;
public class LocalHttpConnectorTest
{
private Server _server;
private LocalHttpConnector _connector;
private LocalConnector _connector;
@Before
public void init() throws Exception
{
_server = new Server();
_connector = new LocalHttpConnector();
_connector = new LocalConnector(_server);
_server.addConnector(_connector);
_server.setHandler(new DumpHandler());
_server.start();

View File

@ -54,7 +54,7 @@ public class NetworkTrafficListenerTest
server.setSendDateHeader(false);
server.setSendServerVersion(false);
connector = new NetworkTrafficSelectChannelConnector();
connector = new NetworkTrafficSelectChannelConnector(server);
server.addConnector(connector);
server.setHandler(handler);
server.start();

View File

@ -27,6 +27,7 @@ import static org.junit.Assert.assertTrue;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.server.handler.ContextHandler;
@ -42,13 +43,13 @@ import org.junit.Test;
public class RFC2616Test
{
private Server server;
private LocalHttpConnector connector;
private LocalConnector connector;
@Before
public void init() throws Exception
{
server = new Server();
connector = new LocalHttpConnector();
connector = new LocalConnector(server);
connector.setIdleTimeout(10000);
server.addConnector(connector);
@ -360,7 +361,7 @@ public class RFC2616Test
// Default Host
offset=0;
response=connector.getResponses("GET http://VirtualHost:8888/path/R1 HTTP/1.1\n"+"Host: wronghost\n"+"\n");
response=connector.getResponses("GET http://VirtualHost:8888/path/R1 HTTP/1.1\n"+"Host: wronghost\n"+"Connection: close\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","Default host")+1;
offset=checkContains(response,offset,"Virtual Dump","virtual host")+1;
offset=checkContains(response,offset,"pathInfo=/path/R1","Default host")+1;
@ -374,14 +375,14 @@ public class RFC2616Test
// Default Host
offset=0;
response=connector.getResponses("GET /path/R1 HTTP/1.1\n"+"Host: localhost\n"+"\n");
response=connector.getResponses("GET /path/R1 HTTP/1.1\n"+"Host: localhost\n"+"Connection: close\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","Default host")+1;
offset=checkContains(response,offset,"Dump HttpHandler","Default host")+1;
offset=checkContains(response,offset,"pathInfo=/path/R1","Default host")+1;
// Virtual Host
offset=0;
response=connector.getResponses("GET /path/R2 HTTP/1.1\n"+"Host: VirtualHost\n"+"\n");
response=connector.getResponses("GET /path/R2 HTTP/1.1\n"+"Host: VirtualHost\n"+"Connection: close\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","Default host")+1;
offset=checkContains(response,offset,"Virtual Dump","virtual host")+1;
offset=checkContains(response,offset,"pathInfo=/path/R2","Default host")+1;
@ -395,14 +396,14 @@ public class RFC2616Test
// Virtual Host
offset=0;
response=connector.getResponses("GET /path/R1 HTTP/1.1\n"+"Host: VirtualHost\n"+"\n");
response=connector.getResponses("GET /path/R1 HTTP/1.1\n"+"Host: VirtualHost\n"+"Connection: close\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","2. virtual host field")+1;
offset=checkContains(response,offset,"Virtual Dump","2. virtual host field")+1;
offset=checkContains(response,offset,"pathInfo=/path/R1","2. virtual host field")+1;
// Virtual Host case insensitive
offset=0;
response=connector.getResponses("GET /path/R1 HTTP/1.1\n"+"Host: ViRtUalhOst\n"+"\n");
response=connector.getResponses("GET /path/R1 HTTP/1.1\n"+"Host: ViRtUalhOst\n"+"Connection: close\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","2. virtual host field")+1;
offset=checkContains(response,offset,"Virtual Dump","2. virtual host field")+1;
offset=checkContains(response,offset,"pathInfo=/path/R1","2. virtual host field")+1;
@ -422,7 +423,7 @@ public class RFC2616Test
int offset=0;
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"\n");
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"\n",250,TimeUnit.MILLISECONDS);
offset=checkContains(response,offset,"HTTP/1.1 200 OK\015\012","8.1.2 default")+10;
checkContains(response,offset,"Content-Length: ","8.1.2 default");
@ -490,7 +491,7 @@ public class RFC2616Test
{
int offset=0;
// Expect 100
LocalHttpConnector.LocalEndPoint endp =connector.executeRequest("GET /R1 HTTP/1.1\n"+
LocalConnector.LocalEndPoint endp =connector.executeRequest("GET /R1 HTTP/1.1\n"+
"Host: localhost\n"+
"Connection: close\n"+
"Expect: 100-continue\n"+
@ -754,19 +755,19 @@ public class RFC2616Test
// HTTP/1.0 OK with no host
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.0\n"+"\n");
response=connector.getResponses("GET /R1 HTTP/1.0\n"+"Connection: close\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","200")+1;
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"\n");
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Connection: close\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 400","400")+1;
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"\n");
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host: localhost\n"+"Connection: close\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","200")+1;
offset=0;
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host:\n"+"\n");
response=connector.getResponses("GET /R1 HTTP/1.1\n"+"Host:\n"+"Connection: close\n"+"\n");
offset=checkContains(response,offset,"HTTP/1.1 200","200")+1;
}
@ -898,7 +899,7 @@ public class RFC2616Test
}
}
private void checkContentRange(LocalHttpConnector listener, String tname, String path, String reqRanges, int expectedStatus, String expectedRange, String expectedData)
private void checkContentRange(LocalConnector listener, String tname, String path, String reqRanges, int expectedStatus, String expectedRange, String expectedData)
{
try
{

View File

@ -13,7 +13,13 @@
package org.eclipse.jetty.server;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNotSame;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.File;
@ -25,6 +31,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
@ -49,19 +56,19 @@ public class RequestTest
{
private static final Logger LOG = Log.getLogger(RequestTest.class);
private Server _server;
private LocalHttpConnector _connector;
private LocalConnector _connector;
private RequestHandler _handler;
@Before
public void init() throws Exception
{
_server = new Server();
_connector = new LocalHttpConnector();
_connector.setRequestHeaderSize(512);
_connector.setRequestBufferSize(1024);
_connector.setResponseHeaderSize(512);
_connector.setResponseBufferSize(2048);
_connector.setForwarded(true);
_connector = new LocalConnector(_server);
_connector.getConnectionFactory().getHttpConfig().setRequestHeaderSize(512);
_connector.getConnectionFactory().getHttpConfig().setRequestBufferSize(1024);
_connector.getConnectionFactory().getHttpConfig().setResponseHeaderSize(512);
_connector.getConnectionFactory().getHttpConfig().setResponseBufferSize(2048);
_connector.getConnectionFactory().getHttpConfig().setForwarded(true);
_server.addConnector(_connector);
_handler = new RequestHandler();
_server.setHandler(_handler);
@ -80,6 +87,7 @@ public class RequestTest
{
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response)
{
Map map = null;
@ -110,6 +118,7 @@ public class RequestTest
String request="GET /?param=%ZZaaa HTTP/1.1\r\n"+
"Host: whatever\r\n"+
"Content-Type: text/html;charset=utf8\n"+
"Connection: close\n"+
"\n";
String responses=_connector.getResponses(request);
@ -122,6 +131,7 @@ public class RequestTest
{
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response)
{
try
@ -155,6 +165,7 @@ public class RequestTest
"Host: whatever\r\n"+
"Content-Type: multipart/form-data; boundary=\"AaB03x\"\r\n"+
"Content-Length: "+multipart.getBytes().length+"\r\n"+
"Connection: close\r\n"+
"\r\n"+
multipart;
@ -167,6 +178,7 @@ public class RequestTest
{
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response)
{
String value=request.getParameter("param");
@ -179,6 +191,7 @@ public class RequestTest
String request="GET /?param=aaa%E7bbb HTTP/1.1\r\n"+
"Host: whatever\r\n"+
"Content-Type: text/html;charset=utf8\n"+
"Connection: close\n"+
"\n";
String responses=_connector.getResponses(request);
@ -199,6 +212,7 @@ public class RequestTest
String request="GET / HTTP/1.1\r\n"+
"Host: whatever.com:\r\n"+
"Content-Type: text/html;charset=utf8\n"+
"Connection: close\n"+
"\n";
String responses=_connector.getResponses(request);
@ -213,6 +227,7 @@ public class RequestTest
final ArrayList<String> results = new ArrayList<String>();
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response)
{
results.add(request.getContentType());
@ -240,6 +255,7 @@ public class RequestTest
"GET / HTTP/1.1\n"+
"Host: whatever\n"+
"Content-Type: text/html; other=foo ; blah=\"charset=wrong;\" ; charset = \" x=z; \" ; more=values \n"+
"Connection: close\n"+
"\n"
);
@ -263,6 +279,7 @@ public class RequestTest
final ArrayList<String> results = new ArrayList<String>();
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response)
{
results.add(request.getRemoteAddr());
@ -305,10 +322,11 @@ public class RequestTest
"GET / HTTP/1.1\n"+
"Host: [::1]:8888\n"+
"Connection: close\n"+
"x-forwarded-for: remote\n"+
"x-forwarded-proto: https\n"+
"\n"
);
"\n",10,TimeUnit.SECONDS);
int i=0;
assertEquals("0.0.0.0",results.get(i++));
@ -345,6 +363,7 @@ public class RequestTest
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response)
{
//assertEquals(request.getContentLength(), ((Request)request).getContentRead());
@ -377,6 +396,7 @@ public class RequestTest
{
Handler handler = new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
ServletException
{
@ -422,6 +442,7 @@ public class RequestTest
{
Handler handler = new AbstractHandler()
{
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException,
ServletException
{
@ -506,6 +527,7 @@ public class RequestTest
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException
{
response.getOutputStream().println("Hello World");
@ -573,6 +595,7 @@ public class RequestTest
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException
{
response.setHeader("Connection","TE");
@ -609,6 +632,7 @@ public class RequestTest
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException
{
javax.servlet.http.Cookie[] ca = request.getCookies();
@ -625,6 +649,7 @@ public class RequestTest
response=_connector.getResponses(
"GET / HTTP/1.1\n"+
"Host: whatever\n"+
"Connection: close\n"+
"\n"
);
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -636,6 +661,7 @@ public class RequestTest
"GET / HTTP/1.1\n"+
"Host: whatever\n"+
"Cookie: name=quoted=\\\"value\\\"\n" +
"Connection: close\n"+
"\n"
);
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -648,6 +674,7 @@ public class RequestTest
"GET / HTTP/1.1\n"+
"Host: whatever\n"+
"Cookie: name=value; other=\"quoted=;value\"\n" +
"Connection: close\n"+
"\n"
);
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -669,6 +696,7 @@ public class RequestTest
"Host: whatever\n"+
"Other: header\n"+
"Cookie: name=value; other=\"quoted=;value\"\n" +
"Connection: close\n"+
"\n"
);
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -692,6 +720,7 @@ public class RequestTest
"Host: whatever\n"+
"Other: header\n"+
"Cookie: name=value; other=\"othervalue\"\n" +
"Connection: close\n"+
"\n"
);
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -743,6 +772,7 @@ public class RequestTest
"Host: whatever\n"+
"Other: header\n"+
"Cookie: __utmz=14316.133020.1.1.utr=gna.de|ucn=(real)|utd=reral|utct=/games/hen-one,gnt-50-ba-keys:key,2072262.html\n"+
"Connection: close\n"+
"\n"
);
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
@ -759,6 +789,7 @@ public class RequestTest
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response)
{
for (int i=0;i<cookie.length; i++)
@ -851,6 +882,7 @@ public class RequestTest
_handler._checker = new RequestTester()
{
@Override
public boolean check(HttpServletRequest request,HttpServletResponse response)
{
return "b".equals(request.getParameter("a")) && request.getParameter("c")==null;
@ -883,6 +915,7 @@ public class RequestTest
private RequestTester _checker;
private String _content;
@Override
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
((Request)request).setHandled(true);

View File

@ -13,6 +13,11 @@
package org.eclipse.jetty.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
@ -24,6 +29,7 @@ import java.util.Locale;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import javax.servlet.ServletException;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
@ -32,9 +38,10 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpGenerator.ResponseInfo;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.io.AbstractAsyncConnection;
import org.eclipse.jetty.io.AsyncByteArrayEndPoint;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.AbstractEndPoint;
import org.eclipse.jetty.io.ByteArrayEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.session.HashSessionIdManager;
@ -45,18 +52,13 @@ import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
/**
*
*/
public class ResponseTest
{
private Server _server;
private LocalHttpConnector _connector;
private LocalConnector _connector;
private HttpChannel _channel;
private ScheduledExecutorService _timer;
@ -64,15 +66,15 @@ public class ResponseTest
public void init() throws Exception
{
_server = new Server();
_connector = new LocalHttpConnector();
_connector = new LocalConnector(_server);
_server.addConnector(_connector);
_server.setHandler(new DumpHandler());
_server.start();
_timer=new ScheduledThreadPoolExecutor(1);
AsyncByteArrayEndPoint endp = new AsyncByteArrayEndPoint(_timer,5000);
AbstractEndPoint endp = new ByteArrayEndPoint(_timer,5000);
HttpInput input = new HttpInput();
AsyncConnection connection = new AbstractAsyncConnection(endp,new Executor()
Connection connection = new AbstractConnection(endp,new Executor()
{
@Override
public void execute(Runnable command)
@ -81,6 +83,13 @@ public class ResponseTest
}
})
{
@Override
public void onOpen()
{
super.onOpen();
fillInterested();
}
@Override
public void onFillable()
{
@ -100,35 +109,28 @@ public class ResponseTest
@Override
protected void resetBuffer()
{
// TODO Auto-generated method stub
}
@Override
protected void increaseContentBufferSize(int size)
{
// TODO Auto-generated method stub
}
@Override
public ScheduledExecutorService getScheduler()
{
// TODO Auto-generated method stub
return null;
}
@Override
public HttpConnector getHttpConnector()
public HttpConfiguration getHttpConfiguration()
{
// TODO Auto-generated method stub
return null;
}
@Override
protected int getContentBufferSize()
{
// TODO Auto-generated method stub
return 0;
}
@ -142,29 +144,27 @@ public class ResponseTest
@Override
protected void execute(Runnable task)
{
// TODO Auto-generated method stub
}
@Override
protected void completed()
{
// TODO Auto-generated method stub
}
@Override
protected void completeResponse() throws IOException
{
// TODO Auto-generated method stub
}
@Override
protected void commitResponse(ResponseInfo info, ByteBuffer content) throws IOException
{
// TODO Auto-generated method stub
}
@Override
public Connector getConnector()
{
return null;
}
};
}

View File

@ -21,7 +21,7 @@ public class SelectChannelAsyncContextTest extends LocalAsyncContextTest
@Override
protected Connector initConnector()
{
return new SelectChannelConnector();
return new SelectChannelConnector(_server);
}
@Override

View File

@ -13,6 +13,7 @@
package org.eclipse.jetty.server;
import org.junit.After;
import org.junit.Before;
@ -25,6 +26,12 @@ public class SelectChannelConnectorCloseTest extends ConnectorCloseTestBase
public void init() throws Exception
{
System.setProperty("org.eclipse.jetty.util.log.DEBUG","true");
startServer(new SelectChannelConnector());
startServer(new SelectChannelConnector(_server));
}
@After
public void after() throws Exception
{
_server.stop();
}
}

View File

@ -23,7 +23,7 @@ public class SelectChannelServerTest extends HttpServerTestBase
@BeforeClass
public static void init() throws Exception
{
startServer(new SelectChannelConnector());
startServer(new SelectChannelConnector(_server));
}
@Override

View File

@ -13,6 +13,9 @@
package org.eclipse.jetty.server;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
@ -20,12 +23,13 @@ import java.io.PrintWriter;
import java.net.Socket;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.log.Log;
@ -36,9 +40,6 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
public class SelectChannelStatisticsTest
{
private static final Logger LOG = Log.getLogger(SelectChannelStatisticsTest.class);
@ -58,17 +59,17 @@ public class SelectChannelStatisticsTest
_connect = new CyclicBarrier(2);
_server = new Server();
_connector = new SelectChannelConnector()
_connector = new SelectChannelConnector(_server)
{
@Override
protected void endPointClosed(AsyncEndPoint endpoint)
protected void endPointClosed(EndPoint endpoint)
{
//System.err.println("Endpoint closed "+endpoint);
super.endPointClosed(endpoint);
}
@Override
public void connectionClosed(AsyncConnection connection)
public void connectionClosed(Connection connection)
{
//System.err.println("Connection closed "+connection);
super.connectionClosed(connection);

View File

@ -31,7 +31,7 @@ public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
@BeforeClass
public static void init() throws Exception
{
SelectChannelConnector connector = new SelectChannelConnector();
SelectChannelConnector connector = new SelectChannelConnector(_server);
connector.setIdleTimeout(MAX_IDLE_TIME); // 250 msec max idle
startServer(connector);
}

View File

@ -19,7 +19,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicInteger;
@ -27,8 +26,8 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.junit.After;
import org.junit.Assert;
@ -44,12 +43,12 @@ public class SlowClientWithPipelinedRequestTest
public void startServer(Handler handler) throws Exception
{
server = new Server();
connector = new SelectChannelConnector()
connector = new SelectChannelConnector(server,new ConnectionFactory()
{
@Override
protected AsyncConnection newConnection(SocketChannel channel, AsyncEndPoint endpoint)
protected Connection newConnection(Connector connector,EndPoint endpoint)
{
return new HttpConnection(this,endpoint,getServer())
return new HttpConnection(getHttpConfig(),connector,endpoint)
{
@Override
public synchronized void onFillable()
@ -57,10 +56,10 @@ public class SlowClientWithPipelinedRequestTest
handles.incrementAndGet();
super.onFillable();
}
};
}
};
},null,null,null,0,0);
server.addConnector(connector);
connector.setPort(0);
server.setHandler(handler);

View File

@ -85,10 +85,9 @@ public class StressTest
_threads = new QueuedThreadPool();
_threads.setMaxThreads(200);
_server = new Server();
_server.setThreadPool(_threads);
_connector = new SelectChannelConnector(1,1);
_server = new Server(_threads);
_server.manage(_threads);
_connector = new SelectChannelConnector(_server,null,null,null,null,1,1);
_connector.setAcceptQueueSize(5000);
_connector.setIdleTimeout(30000);
_server.addConnector(_connector);

View File

@ -24,7 +24,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.LocalHttpConnector;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.junit.Test;
@ -35,7 +35,7 @@ public class ContextHandlerCollectionTest
public void testVirtualHostNormalization() throws Exception
{
Server server = new Server();
LocalHttpConnector connector = new LocalHttpConnector();
LocalConnector connector = new LocalConnector(server);
server.setConnectors(new Connector[]
{ connector });
@ -93,7 +93,7 @@ public class ContextHandlerCollectionTest
public void testVirtualHostWildcard() throws Exception
{
Server server = new Server();
LocalHttpConnector connector = new LocalHttpConnector();
LocalConnector connector = new LocalConnector(server);
server.setConnectors(new Connector[] { connector });
ContextHandler context = new ContextHandler("/");
@ -133,7 +133,7 @@ public class ContextHandlerCollectionTest
private void checkWildcardHost(boolean succeed, Server server, String[] contextHosts, String[] requestHosts) throws Exception
{
LocalHttpConnector connector = (LocalHttpConnector)server.getConnectors()[0];
LocalConnector connector = (LocalConnector)server.getConnectors()[0];
ContextHandlerCollection handlerCollection = (ContextHandlerCollection)server.getHandler();
ContextHandler context = (ContextHandler)handlerCollection.getHandlers()[0];
IsHandledHandler handler = (IsHandledHandler)context.getHandler();
@ -144,7 +144,7 @@ public class ContextHandlerCollectionTest
for(String host : requestHosts)
{
connector.getResponses("GET / HTTP/1.1\n" + "Host: "+host+"\n\n");
connector.getResponses("GET / HTTP/1.1\n" + "Host: "+host+"\nConnection:close\n\n");
if(succeed)
assertTrue("'"+host+"' should have been handled.",handler.isHandled());
else

View File

@ -31,7 +31,7 @@ import javax.servlet.http.HttpServletResponse;
import junit.framework.Assert;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.LocalHttpConnector;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.resource.Resource;
@ -58,7 +58,7 @@ public class ContextHandlerTest
public void testVirtualHostNormalization() throws Exception
{
Server server = new Server();
LocalHttpConnector connector = new LocalHttpConnector();
LocalConnector connector = new LocalConnector(server);
server.setConnectors(new Connector[]
{ connector });
@ -117,7 +117,7 @@ public class ContextHandlerTest
public void testContextGetContext() throws Exception
{
Server server = new Server();
LocalHttpConnector connector = new LocalHttpConnector();
LocalConnector connector = new LocalConnector(server);
server.setConnectors(new Connector[] { connector });
ContextHandlerCollection contexts = new ContextHandlerCollection();
server.setHandler(contexts);
@ -149,7 +149,7 @@ public class ContextHandlerTest
public void testContextVirtualGetContext() throws Exception
{
Server server = new Server();
LocalHttpConnector connector = new LocalHttpConnector();
LocalConnector connector = new LocalConnector(server);
server.setConnectors(new Connector[] { connector });
ContextHandlerCollection contexts = new ContextHandlerCollection();
server.setHandler(contexts);
@ -196,7 +196,7 @@ public class ContextHandlerTest
public void testVirtualHostWildcard() throws Exception
{
Server server = new Server();
LocalHttpConnector connector = new LocalHttpConnector();
LocalConnector connector = new LocalConnector(server);
server.setConnectors(new Connector[] { connector });
ContextHandler context = new ContextHandler("/");
@ -365,7 +365,7 @@ public class ContextHandlerTest
{
Server server = new Server();
server.setUncheckedPrintWriter(true);
LocalHttpConnector connector = new LocalHttpConnector();
LocalConnector connector = new LocalConnector(server);
server.setConnectors(new Connector[] { connector });
ContextHandler context = new ContextHandler("/");
WriterHandler handler = new WriterHandler();
@ -376,10 +376,11 @@ public class ContextHandlerTest
{
server.start();
String response = connector.getResponses("GET / HTTP/1.1\n" + "Host: www.example.com.\n\n");
String response = connector.getResponses("GET / HTTP/1.1\n" + "Host: www.example.com.\nConnection:close\n\n");
Assert.assertTrue(response.indexOf("Goodbye")>0);
Assert.assertTrue(response.indexOf("dead")<0);
Thread.sleep(100);
Assert.assertTrue(handler.error);
Assert.assertTrue(handler.throwable!=null);
}
@ -391,14 +392,14 @@ public class ContextHandlerTest
private void checkWildcardHost(boolean succeed, Server server, String[] contextHosts, String[] requestHosts) throws Exception
{
LocalHttpConnector connector = (LocalHttpConnector)server.getConnectors()[0];
LocalConnector connector = (LocalConnector)server.getConnectors()[0];
ContextHandler context = (ContextHandler)server.getHandler();
context.setVirtualHosts(contextHosts);
IsHandledHandler handler = (IsHandledHandler)context.getHandler();
for(String host : requestHosts)
{
connector.getResponses("GET / HTTP/1.1\n" + "Host: "+host+"\n\n");
connector.getResponses("GET / HTTP/1.1\n" + "Host: "+host+"\nConnection:close\n\n");
if(succeed)
assertTrue("'"+host+"' should have been handled.",handler.isHandled());
else
@ -431,8 +432,8 @@ public class ContextHandlerTest
private static final class WriterHandler extends AbstractHandler
{
boolean error;
Throwable throwable;
volatile boolean error;
volatile Throwable throwable;
public void handle(String s, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException

View File

@ -63,7 +63,7 @@ public class IPAccessHandlerTest
throws Exception
{
_server = new Server();
_connector = new SelectChannelConnector();
_connector = new SelectChannelConnector(_server);
_server.setConnectors(new Connector[] { _connector });
_handler = new IPAccessHandler();

View File

@ -43,7 +43,7 @@ public class ResourceHandlerTest extends TestCase
public void setUp() throws Exception
{
_server = new Server();
_connector = new SelectChannelConnector();
_connector = new SelectChannelConnector(_server);
_server.setConnectors(new Connector[] { _connector });
_resourceHandler = new ResourceHandler();

View File

@ -31,7 +31,7 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.continuation.Continuation;
import org.eclipse.jetty.continuation.ContinuationListener;
import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.server.LocalHttpConnector;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.junit.After;
@ -41,7 +41,7 @@ import org.junit.Test;
public class StatisticsHandlerTest
{
private Server _server;
private LocalHttpConnector _connector;
private LocalConnector _connector;
private LatchHandler _latchHandler;
private StatisticsHandler _statsHandler;
@ -50,7 +50,7 @@ public class StatisticsHandlerTest
{
_server = new Server();
_connector = new LocalHttpConnector();
_connector = new LocalConnector(_server);
_server.addConnector(_connector);
_connector.getStatistics().start();

View File

@ -11,11 +11,6 @@
//You may elect to redistribute this code under either of these licenses.
//========================================================================
// JettyTest.java --
//
// Junit test that shows the Jetty SSL bug.
//
package org.eclipse.jetty.server.ssl;
import java.io.BufferedReader;
@ -36,9 +31,10 @@ import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
@ -47,7 +43,7 @@ import org.eclipse.jetty.server.handler.AbstractHandler;
*/
public class SSLCloseTest extends TestCase
{
private static AsyncEndPoint __endp;
private static EndPoint __endp;
private static class CredulousTM implements TrustManager, X509TrustManager
{
public X509Certificate[] getAcceptedIssuers()
@ -77,14 +73,14 @@ public class SSLCloseTest extends TestCase
public void testClose() throws Exception
{
Server server=new Server();
SslSelectChannelConnector connector=new SslSelectChannelConnector();
SelectChannelConnector connector=new SelectChannelConnector(server,true);
String keystore = System.getProperty("user.dir")+File.separator+"src"+File.separator+"test"+File.separator+"resources"+File.separator+"keystore";
connector.setPort(0);
connector.getSslContextFactory().setKeyStorePath(keystore);
connector.getSslContextFactory().setKeyStorePassword("storepwd");
connector.getSslContextFactory().setKeyManagerPassword("keypwd");
connector.getConnectionFactory().getSslContextFactory().setKeyStorePath(keystore);
connector.getConnectionFactory().getSslContextFactory().setKeyStorePassword("storepwd");
connector.getConnectionFactory().getSslContextFactory().setKeyManagerPassword("keypwd");
server.setConnectors(new Connector[]
{ connector });
@ -98,11 +94,13 @@ public class SSLCloseTest extends TestCase
int port=connector.getLocalPort();
// System.err.println("write:"+i);
Socket socket=ctx.getSocketFactory().createSocket("localhost",port);
OutputStream os=socket.getOutputStream();
os.write("GET /test HTTP/1.1\r\nHost:test\r\nConnection:close\r\n\r\n".getBytes());
os.write((
"GET /test HTTP/1.1\r\n"+
"Host:test\r\n"+
"Connection:close\r\n\r\n").getBytes());
os.flush();
BufferedReader in =new BufferedReader(new InputStreamReader(socket.getInputStream()));
@ -110,18 +108,14 @@ public class SSLCloseTest extends TestCase
String line;
while ((line=in.readLine())!=null)
{
// System.err.println(line);
if (line.trim().length()==0)
break;
}
Thread.sleep(2000);
// System.err.println(__endp);
while ((line=in.readLine())!=null)
//System.err.println(line);
Thread.yield();
}

View File

@ -45,11 +45,13 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.hamcrest.Matchers;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
@ -81,23 +83,23 @@ public class SSLEngineTest
private static final int BODY_SIZE=300;
private Server server;
private SslSelectChannelConnector connector;
private SelectChannelConnector connector;
@Before
public void startServer() throws Exception
{
server=new Server();
connector=new SslSelectChannelConnector();
connector=new SelectChannelConnector(server,true);
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
connector.setPort(0);
SslContextFactory cf = connector.getSslContextFactory();
SslContextFactory cf = connector.getConnectionFactory().getSslContextFactory();
cf.setKeyStorePath(keystore);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
connector.setRequestBufferSize(512);
connector.setRequestHeaderSize(512);
connector.getConnectionFactory().getHttpConfig().setRequestBufferSize(512);
connector.getConnectionFactory().getHttpConfig().setRequestHeaderSize(512);
server.setConnectors(new Connector[]{connector });
}
@ -108,8 +110,38 @@ public class SSLEngineTest
server.stop();
server.join();
}
@Test
public void testHelloWorld() throws Exception
{
server.setHandler(new HelloWorldHandler());
server.start();
server.dumpStdErr();
SSLContext ctx=SSLContext.getInstance("TLS");
ctx.init(null,SslContextFactory.TRUST_ALL_CERTS,new java.security.SecureRandom());
int port=connector.getLocalPort();
Socket client=ctx.getSocketFactory().createSocket("localhost",port);
OutputStream os=client.getOutputStream();
String request =
"GET / HTTP/1.1\r\n"+
"Host: localhost:"+port+"\r\n"+
"Connection: close\r\n"+
"\r\n";
os.write(request.getBytes());
os.flush();
String response = IO.toString(client.getInputStream());
assertThat(response,Matchers.containsString("200 OK"));
assertThat(response,Matchers.containsString(HELLO_WORLD));
}
@Test
public void testBigResponse() throws Exception
{

View File

@ -40,7 +40,6 @@ import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
public class SSLSelectChannelConnectorLoadTest
@ -53,11 +52,11 @@ public class SSLSelectChannelConnectorLoadTest
public static void startServer() throws Exception
{
server = new Server();
connector = new SslSelectChannelConnector();
connector = new SslSelectChannelConnector(server);
server.addConnector(connector);
String keystorePath = System.getProperty("basedir", ".") + "/src/test/resources/keystore";
SslContextFactory cf = connector.getSslContextFactory();
SslContextFactory cf = connector.getConnectionFactory().getSslContextFactory();
cf.setKeyStorePath(keystorePath);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
@ -69,7 +68,7 @@ public class SSLSelectChannelConnectorLoadTest
server.start();
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(new FileInputStream(connector.getKeystore()), "storepwd".toCharArray());
keystore.load(new FileInputStream(connector.getConnectionFactory().getSslContextFactory().getKeyStorePath()), "storepwd".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
sslContext = SSLContext.getInstance("SSL");

View File

@ -25,6 +25,7 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.eclipse.jetty.server.HttpServerTestBase;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.BeforeClass;
import org.junit.Ignore;
@ -49,10 +50,10 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
@BeforeClass
public static void init() throws Exception
{
SslSelectChannelConnector connector = new SslSelectChannelConnector();
SelectChannelConnector connector = new SelectChannelConnector(_server,true);
String keystorePath = System.getProperty("basedir",".") + "/src/test/resources/keystore";
SslContextFactory cf = connector.getSslContextFactory();
SslContextFactory cf = connector.getConnectionFactory().getSslContextFactory();
cf.setKeyStorePath(keystorePath);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
@ -62,7 +63,7 @@ public class SelectChannelServerSslTest extends HttpServerTestBase
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(new FileInputStream(connector.getKeystore()), "storepwd".toCharArray());
keystore.load(new FileInputStream(connector.getConnectionFactory().getSslContextFactory().getKeyStorePath()), "storepwd".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
__sslContext = SSLContext.getInstance("TLS");

View File

@ -20,6 +20,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.SocketTimeoutException;
import java.nio.channels.SelectionKey;
import java.nio.channels.SocketChannel;
import java.util.Arrays;
import java.util.concurrent.Callable;
@ -34,7 +35,6 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLSocket;
import javax.servlet.ServletException;
import javax.servlet.ServletInputStream;
@ -42,11 +42,11 @@ import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.AsyncConnection;
import org.eclipse.jetty.io.AsyncEndPoint;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.io.SelectChannelEndPoint;
import org.eclipse.jetty.io.SelectorManager.ManagedSelector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
@ -73,7 +73,6 @@ public class SslBytesServerTest extends SslBytesTest
private int serverPort;
private SSLContext sslContext;
private SimpleProxy proxy;
private Runnable idleHook;
@Before
public void init() throws Exception
@ -81,76 +80,26 @@ public class SslBytesServerTest extends SslBytesTest
threadPool = Executors.newCachedThreadPool();
server = new Server();
SslSelectChannelConnector connector = new SslSelectChannelConnector()
SelectChannelConnector connector = new SelectChannelConnector(server,true)
{
@Override
protected SslConnection newSslConnection(AsyncEndPoint endPoint, SSLEngine engine)
protected SelectChannelEndPoint newEndPoint(SocketChannel channel, ManagedSelector selectSet, SelectionKey key) throws IOException
{
serverEndPoint.set(endPoint);
return super.newSslConnection(endPoint, engine);
// return new SslConnection(engine, endPoint)
// {
// @Override
// public Connection handle() throws IOException
// {
// sslHandles.incrementAndGet();
// return super.handle();
// }
//
// @Override
// protected SslEndPoint newSslEndPoint()
// {
// return new SslEndPoint()
// {
// @Override
// public int flush(ByteBuffer buffer) throws IOException
// {
// sslFlushes.incrementAndGet();
// return super.flush(buffer);
// }
// };
// }
//
// @Override
// public void onIdleExpired(long idleForMs)
// {
// final Runnable idleHook = SslBytesServerTest.this.idleHook;
// if (idleHook != null)
// idleHook.run();
// super.onIdleExpired(idleForMs);
// }
// };
}
@Override
protected AsyncConnection newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint)
{
return super.newPlainConnection(channel, endPoint);
// return new HttpConnection(this, endPoint, getServer())
// {
// @Override
// protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endPoint, HttpParser.EventHandler requestHandler)
// {
// return new HttpParser(requestBuffers, endPoint, requestHandler)
// {
// @Override
// public int parseNext() throws IOException
// {
// httpParses.incrementAndGet();
// return super.parseNext();
// }
// };
// }
// };
SelectChannelEndPoint endp = super.newEndPoint(channel,selectSet,key);
serverEndPoint.set(endp);
return endp;
}
};
connector.setIdleTimeout(idleTimeout);
// connector.setPort(5870);
connector.setPort(0);
File keyStore = MavenTestingUtils.getTestResourceFile("keystore");
SslContextFactory cf = connector.getSslContextFactory();
SslContextFactory cf = connector.getConnectionFactory().getSslContextFactory();
cf.setKeyStorePath(keyStore.getAbsolutePath());
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
@ -1573,33 +1522,8 @@ public class SslBytesServerTest extends SslBytesTest
public void testRequestConcurrentWithIdleExpiration() throws Exception
{
final SSLSocket client = newClient();
final OutputStream clientOutput = client.getOutputStream();
final CountDownLatch latch = new CountDownLatch(1);
idleHook = new Runnable()
{
public void run()
{
if (latch.getCount() == 0)
return;
try
{
// Send request
clientOutput.write(("" +
"GET / HTTP/1.1\r\n" +
"Host: localhost\r\n" +
"\r\n").getBytes("UTF-8"));
clientOutput.flush();
latch.countDown();
}
catch (Exception x)
{
// Latch won't trigger and test will fail
x.printStackTrace();
}
}
};
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
client.startHandshake();
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));

View File

@ -1,262 +0,0 @@
package org.eclipse.jetty.server.ssl;
//========================================================================
//Copyright 2011-2012 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.
//========================================================================
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLProtocolException;
import javax.net.ssl.SSLSession;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Ignore;
import org.junit.Test;
public class SslRenegotiateTest
{
private static final Logger LOG = Log.getLogger(SslRenegotiateTest.class);
private ByteBuffer _outAppB;
private ByteBuffer _outPacketB;
private ByteBuffer _inAppB;
private ByteBuffer _inPacketB;
private SocketChannel _socket;
private SSLEngine _engine;
@Test
public void testRenegNIO() throws Exception
{
// TODO This test breaks on JVMs with the fix
// doRequests(new SslSelectChannelConnector(),true);
}
@Test
@Ignore
public void testNoRenegNIO() throws Exception
{
doRequests(new SslSelectChannelConnector(),false);
}
@Test
public void testRenegBIO() throws Exception
{
// TODO - this test is too non deterministic due to call back timing
// doRequests(new SslSocketConnector(),true);
}
@Test
public void testNoRenegBIO() throws Exception
{
// TODO - this test is too non deterministic due to call back timing
// doRequests(new SslSocketConnector(),false);
}
private void doRequests(SslConnector connector, boolean reneg) throws Exception
{
Server server=new Server();
try
{
String keystore = MavenTestingUtils.getTestResourceFile("keystore").getAbsolutePath();
SslContextFactory cf = connector.getSslContextFactory();
cf.setKeyStorePath(keystore);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
cf.setAllowRenegotiate(reneg);
server.setConnectors(new Connector[] { connector });
server.setHandler(new HelloWorldHandler());
server.start();
SocketAddress addr = new InetSocketAddress("localhost",connector.getLocalPort());
_socket = SocketChannel.open(addr);
_socket.configureBlocking(true);
SSLContext context=SSLContext.getInstance("SSL");
context.init( null, SslContextFactory.TRUST_ALL_CERTS, new java.security.SecureRandom() );
_engine = context.createSSLEngine();
_engine.setUseClientMode(true);
SSLSession session=_engine.getSession();
_outAppB = ByteBuffer.allocate(session.getApplicationBufferSize());
_outPacketB = ByteBuffer.allocate(session.getPacketBufferSize());
_inAppB = ByteBuffer.allocate(session.getApplicationBufferSize());
_inPacketB = ByteBuffer.allocate(session.getPacketBufferSize());
_outAppB.put("GET /1 HTTP/1.1\r\nHost: localhost\r\n\r\n".getBytes(StringUtil.__ISO_8859_1));
_outAppB.flip();
_engine.beginHandshake();
runHandshake();
doWrap();
doUnwrap();
_inAppB.flip();
String response=BufferUtil.toString(_inAppB);
// System.err.println(response);
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
if (response.indexOf("HELLO WORLD")<0)
{
_inAppB.clear();
doUnwrap();
_inAppB.flip();
response=BufferUtil.toString(_inAppB);
}
assertTrue(response.indexOf("HELLO WORLD")>=0);
_inAppB.clear();
_outAppB.clear();
_outAppB.put("GET /2 HTTP/1.1\r\nHost: localhost\r\n\r\n".getBytes(StringUtil.__ISO_8859_1));
_outAppB.flip();
try
{
session.invalidate();
_engine.beginHandshake();
runHandshake();
doWrap();
doUnwrap();
_inAppB.flip();
response=BufferUtil.toString(_inAppB);
assertTrue(response.startsWith("HTTP/1.1 200 OK"));
assertTrue(response.indexOf("HELLO WORLD")>0);
assertTrue(reneg);
}
catch(IOException e)
{
if (!(e instanceof SSLProtocolException))
{
if (reneg)
LOG.warn(e);
assertFalse(reneg);
}
}
}
finally
{
server.stop();
server.join();
}
}
void runHandshake() throws Exception
{
while (true)
{
switch(_engine.getHandshakeStatus())
{
case NEED_TASK:
{
//System.err.println("running task");
_engine.getDelegatedTask().run();
break;
}
case NEED_WRAP:
{
doWrap();
break;
}
case NEED_UNWRAP:
{
doUnwrap();
break;
}
default:
return;
}
}
}
private void doWrap() throws Exception
{
_engine.wrap(_outAppB,_outPacketB);
// System.err.println("wrapped "+result.bytesConsumed()+" to "+result.bytesProduced());
_outPacketB.flip();
while (_outPacketB.hasRemaining())
{
int p = _outPacketB.remaining();
int l =_socket.write(_outPacketB);
// System.err.println("wrote "+l+" of "+p);
}
_outPacketB.clear();
}
private void doUnwrap() throws Exception
{
_inPacketB.clear();
int l=_socket.read(_inPacketB);
// System.err.println("read "+l);
if (l<0)
throw new IOException("EOF");
_inPacketB.flip();
SSLEngineResult result;
do
{
result =_engine.unwrap(_inPacketB,_inAppB);
// System.err.println("unwrapped "+result.bytesConsumed()+" to "+result.bytesProduced()+" "+_engine.getHandshakeStatus());
}
while(result.bytesConsumed()>0 &&
_inPacketB.remaining()>0 &&
(_engine.getHandshakeStatus()==HandshakeStatus.NEED_UNWRAP || _engine.getHandshakeStatus()==HandshakeStatus.NOT_HANDSHAKING));
}
private static class HelloWorldHandler extends AbstractHandler
{
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
//System.err.println("HELLO WORLD HANDLING");
// System.err.println("hello "+baseRequest.getUri());
byte[] b=("HELLO WORLD "+baseRequest.getUri()).getBytes(StringUtil.__UTF8);
response.setContentLength(b.length);
response.getOutputStream().write(b);
response.getOutputStream().flush();
}
}
}

View File

@ -21,6 +21,7 @@ import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
import org.eclipse.jetty.server.ConnectorTimeoutTest;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.BeforeClass;
@ -37,10 +38,10 @@ public class SslSelectChannelTimeoutTest extends ConnectorTimeoutTest
@BeforeClass
public static void init() throws Exception
{
SslSelectChannelConnector connector = new SslSelectChannelConnector();
SelectChannelConnector connector = new SelectChannelConnector(_server,true);
connector.setIdleTimeout(MAX_IDLE_TIME); //250 msec max idle
String keystorePath = System.getProperty("basedir",".") + "/src/test/resources/keystore";
SslContextFactory cf = connector.getSslContextFactory();
SslContextFactory cf = connector.getConnectionFactory().getSslContextFactory();
cf.setKeyStorePath(keystorePath);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
@ -49,7 +50,7 @@ public class SslSelectChannelTimeoutTest extends ConnectorTimeoutTest
startServer(connector);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(new FileInputStream(connector.getKeystore()), "storepwd".toCharArray());
keystore.load(new FileInputStream(connector.getConnectionFactory().getSslContextFactory().getKeyStorePath()), "storepwd".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
__sslContext = SSLContext.getInstance("SSL");

View File

@ -23,7 +23,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.security.KeyStore;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
@ -33,6 +32,7 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.IO;
@ -48,18 +48,18 @@ import org.junit.Test;
public class SslUploadTest
{
private static Server server;
private static SslSelectChannelConnector connector;
private static SelectChannelConnector connector;
private static int total;
@BeforeClass
public static void startServer() throws Exception
{
server = new Server();
connector = new SslSelectChannelConnector();
connector = new SelectChannelConnector(server,true);
server.addConnector(connector);
String keystorePath = System.getProperty("basedir",".") + "/src/test/resources/keystore";
SslContextFactory cf = connector.getSslContextFactory();
SslContextFactory cf = connector.getConnectionFactory().getSslContextFactory();
cf.setKeyStorePath(keystorePath);
cf.setKeyStorePassword("storepwd");
cf.setKeyManagerPassword("keypwd");
@ -83,7 +83,7 @@ public class SslUploadTest
public void test() throws Exception
{
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(new FileInputStream(connector.getKeystore()), "storepwd".toCharArray());
keystore.load(new FileInputStream(connector.getConnectionFactory().getSslContextFactory().getKeyStorePath()), "storepwd".toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
SSLContext sslContext = SSLContext.getInstance("SSL");

View File

@ -34,22 +34,17 @@ import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpContent;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.WriterOutputStream;
import org.eclipse.jetty.server.HttpConnection;
import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.HttpConnector;
import org.eclipse.jetty.server.HttpChannel;
import org.eclipse.jetty.server.HttpOutput;
import org.eclipse.jetty.server.InclusiveByteRange;
import org.eclipse.jetty.server.ResourceCache;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.ssl.SslConnector;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.MultiPartOutputStream;
@ -779,9 +774,9 @@ public class DefaultServlet extends HttpServlet implements ResourceFactory
}
else
{
HttpConnector connector = HttpChannel.getCurrentHttpChannel().getHttpConnector();
// TODO either make this more targeted and/or configurable or just get rid of the choice
direct=!(connector instanceof SslConnector);
// TODO sometimes we should be direct!
Connector connector = HttpChannel.getCurrentHttpChannel().getConnector();
direct=false;
content_length=content.getContentLength();
}

View File

@ -25,7 +25,6 @@ import javax.servlet.FilterConfig;
import javax.servlet.FilterRegistration;
import javax.servlet.ServletException;
import org.eclipse.jetty.servlet.Holder.Source;
import org.eclipse.jetty.util.TypeUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;

View File

@ -17,6 +17,7 @@ import java.io.IOException;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import org.eclipse.jetty.http.PathMap;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.util.TypeUtil;

View File

@ -26,6 +26,7 @@ import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ConcurrentMap;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterChain;

View File

@ -28,9 +28,9 @@ import java.util.Stack;
import javax.servlet.MultipartConfigElement;
import javax.servlet.Servlet;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRegistration;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.ServletSecurityElement;

View File

@ -1,9 +1,7 @@
package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.ByteBuffer;
import java.nio.charset.Charset;
import java.util.EnumSet;
import java.util.Enumeration;
import java.util.Map;
@ -12,24 +10,18 @@ import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.Servlet;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpParser;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.LocalHttpConnector;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.SelectChannelConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.component.AggregateLifeCycle;
import org.eclipse.jetty.util.resource.Resource;
public class ServletTester extends AggregateLifeCycle
{
private final Server _server=new Server();
private final LocalHttpConnector _connector=new LocalHttpConnector();
private final LocalConnector _connector=new LocalConnector(_server);
private final ServletContextHandler _context;
public void setVirtualHosts(String[] vhosts)
{
@ -184,7 +176,7 @@ public class ServletTester extends AggregateLifeCycle
*/
public String createConnector(boolean localhost) throws Exception
{
SelectChannelConnector connector = new SelectChannelConnector();
SelectChannelConnector connector = new SelectChannelConnector(_server);
if (localhost)
connector.setHost("127.0.0.1");
_server.addConnector(connector);
@ -198,9 +190,9 @@ public class ServletTester extends AggregateLifeCycle
)+":"+connector.getLocalPort();
}
public LocalHttpConnector createLocalConnector()
public LocalConnector createLocalConnector()
{
LocalHttpConnector connector = new LocalHttpConnector();
LocalConnector connector = new LocalConnector(_server);
_server.addConnector(connector);
return connector;
}

View File

@ -12,7 +12,11 @@ package org.eclipse.jetty.servlet;
//You may elect to redistribute this code under either of these licenses.
//========================================================================
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
@ -23,7 +27,7 @@ import org.eclipse.jetty.continuation.ContinuationSupport;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpChannelState;
import org.eclipse.jetty.server.LocalHttpConnector;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
import org.eclipse.jetty.server.handler.HandlerList;
@ -31,9 +35,6 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
/**
* This tests verifies that merging of queryStrings works when dispatching
* Requests via {@link Continuation} multiple times.
@ -45,7 +46,7 @@ public class AsyncContextDispatchWithQueryStrings {
private Server _server = new Server();
private ServletContextHandler _contextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
private LocalHttpConnector _connector = new LocalHttpConnector();
private LocalConnector _connector = new LocalConnector(_server);
@Before
public void setUp() throws Exception {

View File

@ -12,9 +12,15 @@ package org.eclipse.jetty.servlet;
//You may elect to redistribute this code under either of these licenses.
//========================================================================
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import javax.servlet.AsyncContext;
import javax.servlet.DispatcherType;
import javax.servlet.ServletException;
@ -24,9 +30,10 @@ import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpServletResponseWrapper;
import junit.framework.Assert;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.LocalHttpConnector;
import org.eclipse.jetty.server.LocalConnector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.DefaultHandler;
@ -35,11 +42,6 @@ import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.hamcrest.Matchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
/**
* This tests the correct functioning of the AsyncContext
*
@ -50,14 +52,14 @@ public class AsyncContextTest
private Server _server;
private ServletContextHandler _contextHandler;
private LocalHttpConnector _connector;
private LocalConnector _connector;
@Before
public void setUp() throws Exception
{
_server = new Server();
_contextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS);
_connector = new LocalHttpConnector();
_connector = new LocalConnector(_server);
_connector.setIdleTimeout(30000);
_server.setConnectors(new Connector[]
{ _connector });

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