Merge branch 'jetty-8' into release-8
This commit is contained in:
commit
574851a830
|
@ -15,3 +15,5 @@ dependencies.
|
|||
The tests do a lot of stress testing, and on some machines it is
|
||||
necessary to set the file descriptor limit to greater than 2048
|
||||
for the tests to all pass successfully.
|
||||
|
||||
Bypass tests by building with -Dmaven.test.skip=true but note that this will not produce some test jars that are leveraged in other places in the build.
|
||||
|
|
32
VERSION.txt
32
VERSION.txt
|
@ -1,4 +1,5 @@
|
|||
jetty-8.1.0-SNAPSHOT
|
||||
+ 367548 jetty-osgi-boot must not import the nested package twice
|
||||
|
||||
jetty-8.1.0.RC2 - 22 December 2011
|
||||
+ 359329 jetty-jaspi must exports its packages. jetty-plus must import
|
||||
|
@ -42,6 +43,37 @@ jetty-8.1.0.RC0 - 30 November 2011
|
|||
+ 364283 can't parse the servlet multipart-config for the web.xml
|
||||
+ 364430 Support web.xml enabled state for servlets
|
||||
|
||||
jetty-7.6.0.RC3 - 05 January 2012
|
||||
+ 367433 added tests to investigate
|
||||
+ 367435 improved D00 test harness
|
||||
+ 367485 HttpExchange canceled before response do not release connection.
|
||||
+ 367502 WebSocket connections should be closed when application context is
|
||||
stopped.
|
||||
+ 367591 corrected configuration.xml version to 7.6
|
||||
+ 367635 Added support for start.d directory
|
||||
+ 637638 limit number of form parameters to avoid DOS
|
||||
+ JETTY-1467 close half closed when idle
|
||||
|
||||
jetty-7.6.0.RC2 - 22 December 2011
|
||||
+ 364638 HttpParser closes if data received while seeking EOF. Tests fixed to
|
||||
cope
|
||||
+ 364921 Made test less time sensitive for ssl
|
||||
+ 364936 use Resource for opening URL streams
|
||||
+ 365267 NullPointerException in bad Address
|
||||
+ 365375 ResourceHandler should be a HandlerWrapper
|
||||
+ 365750 Support WebSocket over SSL, aka wss://
|
||||
+ 365932 Produce jetty-websocket aggregate jar for android use
|
||||
+ 365947 Set headers for Auth failure and retry in http-spi
|
||||
+ 366316 Superfluous printStackTrace on 404
|
||||
+ 366342 Dont persist DosFilter trackers in http session
|
||||
+ 366730 pass the time idle to onIdleExpire
|
||||
+ 367048 test harness for guard on suspended requests
|
||||
+ 367175 SSL 100% CPU spin in case of blocked write and RST.
|
||||
+ 367219 WebSocketClient.open() fails when URI uses default ports.
|
||||
+ JETTY-1460 suppress PrintWriter exceptions
|
||||
+ JETTY-1463 websocket D0 parser should return progress even if no fill done
|
||||
+ JETTY-1465 NPE in ContextHandler.toString
|
||||
|
||||
jetty-7.6.0.RC1 - 04 December 2011
|
||||
+ 352565 cookie httponly flag ignored
|
||||
+ 353285 ServletSecurity annotation ignored
|
||||
|
|
|
@ -29,6 +29,7 @@ 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.nio.BlockingChannelConnector;
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
|
||||
import org.eclipse.jetty.server.ssl.SslSocketConnector;
|
||||
|
@ -49,10 +50,10 @@ public class LikeJettyXml
|
|||
|
||||
// Setup JMX
|
||||
MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
|
||||
mbContainer.start();
|
||||
server.getContainer().addEventListener(mbContainer);
|
||||
server.addBean(mbContainer);
|
||||
mbContainer.addBean(Log.getRootLogger());
|
||||
|
||||
server.addBean(mbContainer,true);
|
||||
mbContainer.addBean(new Log());
|
||||
|
||||
// Setup Threadpool
|
||||
QueuedThreadPool threadPool = new QueuedThreadPool();
|
||||
|
@ -68,6 +69,13 @@ public class LikeJettyXml
|
|||
|
||||
server.setConnectors(new Connector[]
|
||||
{ connector });
|
||||
|
||||
BlockingChannelConnector bConnector = new BlockingChannelConnector();
|
||||
bConnector.setPort(8888);
|
||||
bConnector.setMaxIdleTime(30000);
|
||||
bConnector.setConfidentialPort(8443);
|
||||
bConnector.setAcceptors(1);
|
||||
server.addConnector(bConnector);
|
||||
|
||||
SslSelectChannelConnector ssl_connector = new SslSelectChannelConnector();
|
||||
ssl_connector.setPort(8443);
|
||||
|
|
|
@ -33,10 +33,10 @@ public class ManyServletContexts
|
|||
|
||||
// Setup JMX
|
||||
MBeanContainer mbContainer=new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
|
||||
mbContainer.start();
|
||||
server.getContainer().addEventListener(mbContainer);
|
||||
server.addBean(mbContainer);
|
||||
mbContainer.addBean(Log.getLog());
|
||||
|
||||
server.addBean(mbContainer,true);
|
||||
|
||||
ContextHandlerCollection contexts = new ContextHandlerCollection();
|
||||
server.setHandler(contexts);
|
||||
|
||||
|
|
|
@ -179,21 +179,24 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
|
|||
_generator.setVersion(_exchange.getVersion());
|
||||
|
||||
String method=_exchange.getMethod();
|
||||
String uri = _exchange.getURI();
|
||||
if (_destination.isProxied() && !HttpMethods.CONNECT.equals(method) && uri.startsWith("/"))
|
||||
String uri = _exchange.getRequestURI();
|
||||
if (_destination.isProxied())
|
||||
{
|
||||
boolean secure = _destination.isSecure();
|
||||
String host = _destination.getAddress().getHost();
|
||||
int port = _destination.getAddress().getPort();
|
||||
StringBuilder absoluteURI = new StringBuilder();
|
||||
absoluteURI.append(secure ? HttpSchemes.HTTPS : HttpSchemes.HTTP);
|
||||
absoluteURI.append("://");
|
||||
absoluteURI.append(host);
|
||||
// Avoid adding default ports
|
||||
if (!(secure && port == 443 || !secure && port == 80))
|
||||
absoluteURI.append(":").append(port);
|
||||
absoluteURI.append(uri);
|
||||
uri = absoluteURI.toString();
|
||||
if (!HttpMethods.CONNECT.equals(method) && uri.startsWith("/"))
|
||||
{
|
||||
boolean secure = _destination.isSecure();
|
||||
String host = _destination.getAddress().getHost();
|
||||
int port = _destination.getAddress().getPort();
|
||||
StringBuilder absoluteURI = new StringBuilder();
|
||||
absoluteURI.append(secure ? HttpSchemes.HTTPS : HttpSchemes.HTTP);
|
||||
absoluteURI.append("://");
|
||||
absoluteURI.append(host);
|
||||
// Avoid adding default ports
|
||||
if (!(secure && port == 443 || !secure && port == 80))
|
||||
absoluteURI.append(":").append(port);
|
||||
absoluteURI.append(uri);
|
||||
uri = absoluteURI.toString();
|
||||
}
|
||||
Authentication auth = _destination.getProxyAuthentication();
|
||||
if (auth != null)
|
||||
auth.setCredentials(_exchange);
|
||||
|
@ -394,7 +397,11 @@ public abstract class AbstractHttpConnection extends AbstractConnection implemen
|
|||
}
|
||||
}
|
||||
|
||||
_endp.close();
|
||||
if (_endp.isOpen())
|
||||
{
|
||||
_endp.close();
|
||||
_destination.returnConnection(this, true);
|
||||
}
|
||||
}
|
||||
|
||||
public void setIdleTimeout()
|
||||
|
|
|
@ -16,20 +16,20 @@ package org.eclipse.jetty.client;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import javax.net.ssl.SSLContext;
|
||||
|
||||
import org.eclipse.jetty.client.security.Authentication;
|
||||
import org.eclipse.jetty.client.security.RealmResolver;
|
||||
import org.eclipse.jetty.client.security.SecurityListener;
|
||||
import org.eclipse.jetty.http.HttpBuffers;
|
||||
import org.eclipse.jetty.http.HttpBuffersImpl;
|
||||
import org.eclipse.jetty.http.HttpSchemes;
|
||||
import org.eclipse.jetty.io.Buffers;
|
||||
import org.eclipse.jetty.io.Buffers.Type;
|
||||
import org.eclipse.jetty.util.Attributes;
|
||||
import org.eclipse.jetty.util.AttributesMap;
|
||||
|
@ -66,7 +66,7 @@ import org.eclipse.jetty.util.thread.Timeout;
|
|||
* @see HttpExchange
|
||||
* @see HttpDestination
|
||||
*/
|
||||
public class HttpClient extends HttpBuffers implements Attributes, Dumpable
|
||||
public class HttpClient extends AggregateLifeCycle implements HttpBuffers, Attributes, Dumpable
|
||||
{
|
||||
public static final int CONNECTOR_SOCKET = 0;
|
||||
public static final int CONNECTOR_SELECT_CHANNEL = 2;
|
||||
|
@ -91,44 +91,46 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
|
|||
private int _maxRedirects = 20;
|
||||
private LinkedList<String> _registeredListeners;
|
||||
|
||||
private SslContextFactory _sslContextFactory;
|
||||
private final SslContextFactory _sslContextFactory;
|
||||
|
||||
private RealmResolver _realmResolver;
|
||||
|
||||
private AttributesMap _attributes=new AttributesMap();
|
||||
|
||||
private final HttpBuffersImpl _buffers= new HttpBuffersImpl();
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
private void setBufferTypes()
|
||||
{
|
||||
if (_connectorType==CONNECTOR_SOCKET)
|
||||
{
|
||||
setRequestBufferType(Type.BYTE_ARRAY);
|
||||
setRequestHeaderType(Type.BYTE_ARRAY);
|
||||
setResponseBufferType(Type.BYTE_ARRAY);
|
||||
setResponseHeaderType(Type.BYTE_ARRAY);
|
||||
_buffers.setRequestBufferType(Type.BYTE_ARRAY);
|
||||
_buffers.setRequestHeaderType(Type.BYTE_ARRAY);
|
||||
_buffers.setResponseBufferType(Type.BYTE_ARRAY);
|
||||
_buffers.setResponseHeaderType(Type.BYTE_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
setRequestBufferType(Type.DIRECT);
|
||||
setRequestHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
|
||||
setResponseBufferType(Type.DIRECT);
|
||||
setResponseHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
|
||||
_buffers.setRequestBufferType(Type.DIRECT);
|
||||
_buffers.setRequestHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
|
||||
_buffers.setResponseBufferType(Type.DIRECT);
|
||||
_buffers.setResponseHeaderType(_useDirectBuffers?Type.DIRECT:Type.INDIRECT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public HttpClient()
|
||||
{
|
||||
this(new SslContextFactory());
|
||||
setBufferTypes();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public HttpClient(SslContextFactory sslContextFactory)
|
||||
{
|
||||
_sslContextFactory = sslContextFactory;
|
||||
setBufferTypes();
|
||||
addBean(_sslContextFactory);
|
||||
addBean(_buffers);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
|
@ -149,25 +151,6 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
|
|||
_connectBlocking = connectBlocking;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.component.Dumpable#dump()
|
||||
*/
|
||||
public String dump()
|
||||
{
|
||||
return AggregateLifeCycle.dump(this);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @see org.eclipse.jetty.util.component.Dumpable#dump(java.lang.Appendable, java.lang.String)
|
||||
*/
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
out.append(String.valueOf(this)).append("\n");
|
||||
AggregateLifeCycle.dump(out,indent,Arrays.asList(_threadPool,_connector),_destinations.values());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public void send(HttpExchange exchange) throws IOException
|
||||
{
|
||||
|
@ -183,25 +166,20 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
|
|||
*/
|
||||
public ThreadPool getThreadPool()
|
||||
{
|
||||
if (_threadPool==null)
|
||||
{
|
||||
QueuedThreadPool pool = new QueuedThreadPool();
|
||||
pool.setMaxThreads(16);
|
||||
pool.setDaemon(true);
|
||||
pool.setName("HttpClient");
|
||||
_threadPool = pool;
|
||||
}
|
||||
|
||||
return _threadPool;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
/** Set the ThreadPool.
|
||||
* The threadpool passed is added via {@link #addBean(Object)} so that
|
||||
* it's lifecycle may be managed as a {@link AggregateLifeCycle}.
|
||||
* @param threadPool the threadPool to set
|
||||
*/
|
||||
public void setThreadPool(ThreadPool threadPool)
|
||||
{
|
||||
removeBean(_threadPool);
|
||||
_threadPool = threadPool;
|
||||
addBean(_threadPool);
|
||||
}
|
||||
|
||||
|
||||
|
@ -338,6 +316,7 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
|
|||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Registers a listener that can listen to the stream of execution between the client and the
|
||||
* server and influence events. Sequential calls to the method wrapper sequentially wrap the preceding
|
||||
|
@ -422,33 +401,26 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
|
|||
protected void doStart() throws Exception
|
||||
{
|
||||
setBufferTypes();
|
||||
super.doStart();
|
||||
|
||||
_timeoutQ.setDuration(_timeout);
|
||||
_timeoutQ.setNow();
|
||||
_idleTimeoutQ.setDuration(_idleTimeout);
|
||||
_idleTimeoutQ.setNow();
|
||||
|
||||
if (_threadPool == null)
|
||||
getThreadPool();
|
||||
|
||||
if (_threadPool instanceof LifeCycle)
|
||||
if (_threadPool==null)
|
||||
{
|
||||
((LifeCycle)_threadPool).start();
|
||||
QueuedThreadPool pool = new LocalQueuedThreadPool();
|
||||
pool.setMaxThreads(16);
|
||||
pool.setDaemon(true);
|
||||
pool.setName("HttpClient");
|
||||
_threadPool = pool;
|
||||
addBean(_threadPool,true);
|
||||
}
|
||||
|
||||
_sslContextFactory.start();
|
||||
_connector=(_connectorType == CONNECTOR_SELECT_CHANNEL)?new SelectConnector(this):new SocketConnector(this);
|
||||
addBean(_connector,true);
|
||||
|
||||
if (_connectorType == CONNECTOR_SELECT_CHANNEL)
|
||||
{
|
||||
|
||||
_connector = new SelectConnector(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
_connector = new SocketConnector(this);
|
||||
}
|
||||
_connector.start();
|
||||
super.doStart();
|
||||
|
||||
_threadPool.dispatch(new Runnable()
|
||||
{
|
||||
|
@ -462,7 +434,7 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
|
|||
{
|
||||
Thread.sleep(200);
|
||||
}
|
||||
catch (InterruptedException e)
|
||||
catch (InterruptedException ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -470,32 +442,25 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
|
|||
});
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
long getNow()
|
||||
{
|
||||
return _timeoutQ.getNow();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
_connector.stop();
|
||||
_connector = null;
|
||||
_sslContextFactory.stop();
|
||||
|
||||
if (_threadPool instanceof LifeCycle)
|
||||
{
|
||||
((LifeCycle)_threadPool).stop();
|
||||
}
|
||||
for (HttpDestination destination : _destinations.values())
|
||||
{
|
||||
destination.close();
|
||||
}
|
||||
|
||||
_timeoutQ.cancelAll();
|
||||
_idleTimeoutQ.cancelAll();
|
||||
|
||||
super.doStop();
|
||||
|
||||
if (_threadPool instanceof LocalQueuedThreadPool)
|
||||
{
|
||||
removeBean(_threadPool);
|
||||
_threadPool = null;
|
||||
}
|
||||
|
||||
removeBean(_connector);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -667,6 +632,96 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
|
|||
_maxRedirects = redirects;
|
||||
}
|
||||
|
||||
public int getRequestBufferSize()
|
||||
{
|
||||
return _buffers.getRequestBufferSize();
|
||||
}
|
||||
|
||||
public void setRequestBufferSize(int requestBufferSize)
|
||||
{
|
||||
_buffers.setRequestBufferSize(requestBufferSize);
|
||||
}
|
||||
|
||||
public int getRequestHeaderSize()
|
||||
{
|
||||
return _buffers.getRequestHeaderSize();
|
||||
}
|
||||
|
||||
public void setRequestHeaderSize(int requestHeaderSize)
|
||||
{
|
||||
_buffers.setRequestHeaderSize(requestHeaderSize);
|
||||
}
|
||||
|
||||
public int getResponseBufferSize()
|
||||
{
|
||||
return _buffers.getResponseBufferSize();
|
||||
}
|
||||
|
||||
public void setResponseBufferSize(int responseBufferSize)
|
||||
{
|
||||
_buffers.setResponseBufferSize(responseBufferSize);
|
||||
}
|
||||
|
||||
public int getResponseHeaderSize()
|
||||
{
|
||||
return _buffers.getResponseHeaderSize();
|
||||
}
|
||||
|
||||
public void setResponseHeaderSize(int responseHeaderSize)
|
||||
{
|
||||
_buffers.setResponseHeaderSize(responseHeaderSize);
|
||||
}
|
||||
|
||||
public Type getRequestBufferType()
|
||||
{
|
||||
return _buffers.getRequestBufferType();
|
||||
}
|
||||
|
||||
public Type getRequestHeaderType()
|
||||
{
|
||||
return _buffers.getRequestHeaderType();
|
||||
}
|
||||
|
||||
public Type getResponseBufferType()
|
||||
{
|
||||
return _buffers.getResponseBufferType();
|
||||
}
|
||||
|
||||
public Type getResponseHeaderType()
|
||||
{
|
||||
return _buffers.getResponseHeaderType();
|
||||
}
|
||||
|
||||
public void setRequestBuffers(Buffers requestBuffers)
|
||||
{
|
||||
_buffers.setRequestBuffers(requestBuffers);
|
||||
}
|
||||
|
||||
public void setResponseBuffers(Buffers responseBuffers)
|
||||
{
|
||||
_buffers.setResponseBuffers(responseBuffers);
|
||||
}
|
||||
|
||||
public Buffers getRequestBuffers()
|
||||
{
|
||||
return _buffers.getRequestBuffers();
|
||||
}
|
||||
|
||||
public Buffers getResponseBuffers()
|
||||
{
|
||||
return _buffers.getResponseBuffers();
|
||||
}
|
||||
|
||||
public void setMaxBuffers(int maxBuffers)
|
||||
{
|
||||
_buffers.setMaxBuffers(maxBuffers);
|
||||
}
|
||||
|
||||
public int getMaxBuffers()
|
||||
{
|
||||
return _buffers.getMaxBuffers();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Deprecated
|
||||
public String getTrustStoreLocation()
|
||||
|
@ -839,4 +894,8 @@ public class HttpClient extends HttpBuffers implements Attributes, Dumpable
|
|||
{
|
||||
_sslContextFactory.setSecureRandomAlgorithm(secureRandomAlgorithm);
|
||||
}
|
||||
|
||||
private static class LocalQueuedThreadPool extends QueuedThreadPool
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,10 +18,8 @@ import java.net.SocketTimeoutException;
|
|||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.nio.channels.UnresolvedAddressException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import javax.net.ssl.SSLEngine;
|
||||
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
|
@ -32,7 +30,6 @@ import org.eclipse.jetty.io.nio.AsyncConnection;
|
|||
import org.eclipse.jetty.io.nio.SelectChannelEndPoint;
|
||||
import org.eclipse.jetty.io.nio.SelectorManager;
|
||||
import org.eclipse.jetty.io.nio.SslConnection;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.component.AggregateLifeCycle;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -41,7 +38,7 @@ import org.eclipse.jetty.util.ssl.SslContextFactory;
|
|||
import org.eclipse.jetty.util.thread.Timeout;
|
||||
import org.eclipse.jetty.util.thread.Timeout.Task;
|
||||
|
||||
class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector, Dumpable
|
||||
class SelectConnector extends AggregateLifeCycle implements HttpClient.Connector, Dumpable
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(SelectConnector.class);
|
||||
|
||||
|
@ -49,39 +46,16 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
|
|||
private final Manager _selectorManager=new Manager();
|
||||
private final Map<SocketChannel, Timeout.Task> _connectingChannels = new ConcurrentHashMap<SocketChannel, Timeout.Task>();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @param httpClient the HttpClient this connector is associated to
|
||||
* @param httpClient the HttpClient this connector is associated to. It is
|
||||
* added via the {@link #addBean(Object, boolean)} as an unmanaged bean.
|
||||
*/
|
||||
SelectConnector(HttpClient httpClient)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
super.doStart();
|
||||
|
||||
_selectorManager.start();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
_selectorManager.stop();
|
||||
}
|
||||
|
||||
public String dump()
|
||||
{
|
||||
return AggregateLifeCycle.dump(this);
|
||||
}
|
||||
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
out.append(String.valueOf(this)).append("\n");
|
||||
AggregateLifeCycle.dump(out, indent, Arrays.asList(_selectorManager));
|
||||
addBean(_httpClient,false);
|
||||
addBean(_selectorManager,true);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -97,9 +71,9 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
|
|||
|
||||
if (_httpClient.isConnectBlocking())
|
||||
{
|
||||
channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
|
||||
channel.configureBlocking(false);
|
||||
_selectorManager.register( channel, destination );
|
||||
channel.socket().connect(address.toSocketAddress(), _httpClient.getConnectTimeout());
|
||||
channel.configureBlocking(false);
|
||||
_selectorManager.register( channel, destination );
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -451,11 +425,10 @@ class SelectConnector extends AbstractLifeCycle implements HttpClient.Connector,
|
|||
{
|
||||
return _endp.isCheckForIdle();
|
||||
}
|
||||
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "Upgradable:"+_endp.toString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,15 +14,8 @@
|
|||
|
||||
package org.eclipse.jetty.client;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.SocketTimeoutException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -36,18 +29,22 @@ import org.eclipse.jetty.server.Server;
|
|||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.log.StdErrLog;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
/**
|
||||
*/
|
||||
public abstract class AbstractHttpExchangeCancelTest
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(AbstractHttpExchangeCancelTest.TestHttpExchange.class);
|
||||
|
||||
private Server server;
|
||||
private Connector connector;
|
||||
|
||||
|
@ -362,7 +359,7 @@ public abstract class AbstractHttpExchangeCancelTest
|
|||
|
||||
int status = exchange.waitForDone();
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
|
||||
assertTrue(HttpExchange.STATUS_EXPIRED==status||HttpExchange.STATUS_EXCEPTED==status);
|
||||
assertFalse(exchange.isResponseCompleted());
|
||||
assertTrue(end-start<4000);
|
||||
|
@ -371,6 +368,26 @@ public abstract class AbstractHttpExchangeCancelTest
|
|||
assertFalse(exchange.isAssociated());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHttpExchangeCancelReturnsConnection() throws Exception
|
||||
{
|
||||
TestHttpExchange exchange = new TestHttpExchange();
|
||||
Address address = newAddress();
|
||||
exchange.setAddress(address);
|
||||
long delay = 5000;
|
||||
exchange.setRequestURI("/?action=wait" + delay);
|
||||
|
||||
HttpClient httpClient = getHttpClient();
|
||||
HttpDestination destination = httpClient.getDestination(address, false);
|
||||
int connections = destination.getConnections();
|
||||
httpClient.send(exchange);
|
||||
Thread.sleep(delay / 2);
|
||||
Assert.assertEquals(connections + 1, destination.getConnections());
|
||||
|
||||
exchange.cancel();
|
||||
Assert.assertEquals(connections, destination.getConnections());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
protected abstract HttpClient getHttpClient();
|
||||
|
||||
|
|
|
@ -0,0 +1,118 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.client;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.client.security.Authentication;
|
||||
import org.eclipse.jetty.client.security.BasicAuthentication;
|
||||
import org.eclipse.jetty.client.security.Realm;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ConnectHandler;
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class HttpsProxyAuthenticationTest
|
||||
{
|
||||
private Server _proxy = new Server();
|
||||
private HttpClient _client = new HttpClient();
|
||||
private boolean authHandlerSend;
|
||||
|
||||
@Before
|
||||
public void init() throws Exception
|
||||
{
|
||||
SelectChannelConnector connector = new SelectChannelConnector();
|
||||
_proxy.addConnector(connector);
|
||||
_proxy.setHandler(new ConnectHandler()
|
||||
{
|
||||
@Override
|
||||
protected boolean handleAuthentication(HttpServletRequest request, HttpServletResponse response, String address) throws ServletException, IOException
|
||||
{
|
||||
String authHeader = request.getHeader("Authorization");
|
||||
if (authHeader != null && authHeader.length() > 0)
|
||||
authHandlerSend = true;
|
||||
return super.handleAuthentication(request,response,address);
|
||||
}
|
||||
});
|
||||
_proxy.start();
|
||||
int proxyPort = connector.getLocalPort();
|
||||
|
||||
Authentication authentication = new BasicAuthentication(new Realm()
|
||||
{
|
||||
public String getId()
|
||||
{
|
||||
return "MyRealm";
|
||||
}
|
||||
|
||||
public String getPrincipal()
|
||||
{
|
||||
return "jetty";
|
||||
}
|
||||
|
||||
public String getCredentials()
|
||||
{
|
||||
return "jetty";
|
||||
}
|
||||
});
|
||||
|
||||
_client.setProxy(new Address("localhost", proxyPort));
|
||||
_client.setProxyAuthentication(authentication);
|
||||
_client.start();
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() throws Exception
|
||||
{
|
||||
_client.stop();
|
||||
_proxy.stop();
|
||||
_proxy.join();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void httpsViaProxyThatReturns504ErrorTest() throws Exception
|
||||
{
|
||||
// Assume that we can connect to google
|
||||
String host = "google.com";
|
||||
int port = 443;
|
||||
Socket socket = new Socket();
|
||||
try
|
||||
{
|
||||
socket.connect(new InetSocketAddress(host, port), 1000);
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
Assume.assumeNoException(x);
|
||||
}
|
||||
finally
|
||||
{
|
||||
socket.close();
|
||||
}
|
||||
|
||||
HttpExchange exchange = new ContentExchange();
|
||||
exchange.setURL("https://" + host + ":" + port);
|
||||
exchange.addRequestHeader("behaviour", "google");
|
||||
_client.send(exchange);
|
||||
Assert.assertEquals(HttpExchange.STATUS_COMPLETED, exchange.waitForDone());
|
||||
Assert.assertTrue("Authorization header not set!", authHandlerSend);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
package org.eclipse.jetty.client;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.EOFException;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
@ -34,6 +35,7 @@ import org.eclipse.jetty.io.Connection;
|
|||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.nio.AsyncConnection;
|
||||
import org.eclipse.jetty.io.nio.SslConnection;
|
||||
import org.eclipse.jetty.server.AsyncHttpConnection;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
|
@ -45,7 +47,6 @@ import org.junit.After;
|
|||
import org.junit.Assert;
|
||||
import org.junit.Assume;
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.greaterThan;
|
||||
|
@ -103,7 +104,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
@Override
|
||||
protected AsyncConnection newPlainConnection(SocketChannel channel, AsyncEndPoint endPoint)
|
||||
{
|
||||
return new org.eclipse.jetty.server.AsyncHttpConnection(this, endPoint, getServer())
|
||||
return new AsyncHttpConnection(this, endPoint, getServer())
|
||||
{
|
||||
@Override
|
||||
protected HttpParser newHttpParser(Buffers requestBuffers, EndPoint endPoint, HttpParser.EventHandler requestHandler)
|
||||
|
@ -136,21 +137,32 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
{
|
||||
public void handle(String target, Request request, HttpServletRequest httpRequest, HttpServletResponse httpResponse) throws IOException, ServletException
|
||||
{
|
||||
request.setHandled(true);
|
||||
String contentLength = request.getHeader("Content-Length");
|
||||
if (contentLength != null)
|
||||
try
|
||||
{
|
||||
int length = Integer.parseInt(contentLength);
|
||||
ServletInputStream input = httpRequest.getInputStream();
|
||||
ServletOutputStream output = httpResponse.getOutputStream();
|
||||
byte[] buffer = new byte[32 * 1024];
|
||||
for (int i = 0; i < length; ++i)
|
||||
request.setHandled(true);
|
||||
String contentLength = request.getHeader("Content-Length");
|
||||
if (contentLength != null)
|
||||
{
|
||||
int read = input.read(buffer);
|
||||
if ("/echo".equals(target))
|
||||
output.write(buffer, 0, read);
|
||||
int length = Integer.parseInt(contentLength);
|
||||
ServletInputStream input = httpRequest.getInputStream();
|
||||
ServletOutputStream output = httpResponse.getOutputStream();
|
||||
byte[] buffer = new byte[32 * 1024];
|
||||
while (length > 0)
|
||||
{
|
||||
int read = input.read(buffer);
|
||||
if (read < 0)
|
||||
throw new EOFException();
|
||||
length -= read;
|
||||
if (target.startsWith("/echo"))
|
||||
output.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
if (!(target.endsWith("suppress_exception")))
|
||||
throw x;
|
||||
}
|
||||
}
|
||||
});
|
||||
server.start();
|
||||
|
@ -226,6 +238,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertNull(handshake.get(5, TimeUnit.SECONDS));
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
@ -304,6 +317,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertNull(handshake.get(5, TimeUnit.SECONDS));
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
@ -333,6 +347,129 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
proxy.flushToClient(record);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientHelloIncompleteThenReset() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
threadPool.submit(new Callable<Object>()
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Client Hello
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
byte[] bytes = record.getBytes();
|
||||
byte[] chunk1 = new byte[2 * bytes.length / 3];
|
||||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
|
||||
proxy.sendRSTToServer();
|
||||
|
||||
// Wait a while to detect spinning
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientHelloThenReset() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
threadPool.submit(new Callable<Object>()
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
client.startHandshake();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Client Hello
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
Assert.assertNotNull(record);
|
||||
proxy.flushToServer(record);
|
||||
|
||||
proxy.sendRSTToServer();
|
||||
|
||||
// Wait a while to detect spinning
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandshakeThenReset() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
proxy.sendRSTToServer();
|
||||
|
||||
// Wait a while to detect spinning
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestIncompleteThenReset() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
threadPool.submit(new Callable<Object>()
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"\r\n").getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Application data
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
byte[] bytes = record.getBytes();
|
||||
byte[] chunk1 = new byte[2 * bytes.length / 3];
|
||||
System.arraycopy(bytes, 0, chunk1, 0, chunk1.length);
|
||||
proxy.flushToServer(100, chunk1);
|
||||
|
||||
proxy.sendRSTToServer();
|
||||
|
||||
// Wait a while to detect spinning
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestResponse() throws Exception
|
||||
{
|
||||
|
@ -377,6 +514,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
@ -468,6 +606,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(750));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(750));
|
||||
Assert.assertThat(httpParses.get(), lessThan(150));
|
||||
|
@ -492,20 +631,12 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
proxy.flushToClient(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* Currently this test does not pass.
|
||||
* The problem is a mix of Java not being able to perform SSL half closes
|
||||
* (but SSL supporting it), and the current implementation in Jetty.
|
||||
* See the test below, that passes and whose only difference is that we
|
||||
* delay the output shutdown from the client.
|
||||
*
|
||||
* @throws Exception if the test fails
|
||||
*/
|
||||
@Ignore
|
||||
@Test
|
||||
public void testRequestWithCloseAlertAndShutdown() throws Exception
|
||||
{
|
||||
// See next test on why we only run in Linux
|
||||
Assume.assumeTrue(OS.IS_LINUX);
|
||||
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
|
@ -555,10 +686,11 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
|
||||
// We can't forward to the client, its socket is already closed
|
||||
|
||||
// Socket close
|
||||
record = proxy.readFromClient();
|
||||
Assert.assertNull(String.valueOf(record), record);
|
||||
proxy.flushToServer(record);
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
// Socket close
|
||||
record = proxy.readFromServer();
|
||||
|
@ -569,21 +701,16 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
@Test
|
||||
public void testRequestWithCloseAlert() throws Exception
|
||||
{
|
||||
if ( !OS.IS_LINUX )
|
||||
{
|
||||
// currently we are ignoring this test on anything other then linux
|
||||
|
||||
//http://tools.ietf.org/html/rfc2246#section-7.2.1
|
||||
// Currently we are ignoring this test on anything other then linux
|
||||
// http://tools.ietf.org/html/rfc2246#section-7.2.1
|
||||
|
||||
// TODO (react to this portion which seems to allow win/mac behavior)
|
||||
// It is required that the other party respond with a close_notify alert of its own
|
||||
// and close down the connection immediately, discarding any pending writes. It is not
|
||||
// required for the initiator of the close to wait for the responding
|
||||
// close_notify alert before closing the read side of the connection.
|
||||
Assume.assumeTrue(OS.IS_LINUX);
|
||||
|
||||
// TODO (react to this portion which seems to allow win/mac behavior)
|
||||
//It is required that the other party respond with a close_notify alert of its own
|
||||
//and close down the connection immediately, discarding any pending writes. It is not
|
||||
//required for the initiator of the close to wait for the responding
|
||||
//close_notify alert before closing the read side of the connection.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
|
@ -634,6 +761,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
// We can't forward to the client, its socket is already closed
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
@ -692,6 +820,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
proxy.flushToClient(record);
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
@ -700,7 +829,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testRequestWithBigContentWriteBlockedAndResetException() throws Exception
|
||||
public void testRequestWithBigContentWriteBlockedThenReset() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
|
@ -744,11 +873,63 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
// connection, and this will cause an exception in the
|
||||
// server that is trying to write the data
|
||||
|
||||
proxy.resetServer();
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
proxy.sendRSTToServer();
|
||||
|
||||
// Wait a while to detect spinning
|
||||
TimeUnit.SECONDS.sleep(1);
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRequestWithBigContentReadBlockedThenReset() throws Exception
|
||||
{
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
client.startHandshake();
|
||||
Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
|
||||
|
||||
byte[] data = new byte[128 * 1024];
|
||||
Arrays.fill(data, (byte)'X');
|
||||
final String content = new String(data, "UTF-8");
|
||||
Future<Object> request = threadPool.submit(new Callable<Object>()
|
||||
{
|
||||
public Object call() throws Exception
|
||||
{
|
||||
OutputStream clientOutput = client.getOutputStream();
|
||||
clientOutput.write(("" +
|
||||
"GET /echo_suppress_exception HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Content-Length: " + content.length() + "\r\n" +
|
||||
"\r\n" +
|
||||
content).getBytes("UTF-8"));
|
||||
clientOutput.flush();
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
// Nine TLSRecords will be generated for the request,
|
||||
// but we write only 5 of them, so the server goes in read blocked state
|
||||
for (int i = 0; i < 5; ++i)
|
||||
{
|
||||
// Application data
|
||||
TLSRecord record = proxy.readFromClient();
|
||||
Assert.assertEquals(TLSRecord.Type.APPLICATION, record.getType());
|
||||
proxy.flushToServer(record, 0);
|
||||
}
|
||||
Assert.assertNull(request.get(5, TimeUnit.SECONDS));
|
||||
|
||||
// The server should be read blocked, and we send a RST
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
proxy.sendRSTToServer();
|
||||
|
||||
// Wait a while to detect spinning
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
@ -762,17 +943,17 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
if ( !OS.IS_LINUX )
|
||||
{
|
||||
// currently we are ignoring this test on anything other then linux
|
||||
|
||||
|
||||
//http://tools.ietf.org/html/rfc2246#section-7.2.1
|
||||
|
||||
// TODO (react to this portion which seems to allow win/mac behavior)
|
||||
//It is required that the other party respond with a close_notify alert of its own
|
||||
// TODO (react to this portion which seems to allow win/mac behavior)
|
||||
//It is required that the other party respond with a close_notify alert of its own
|
||||
//and close down the connection immediately, discarding any pending writes. It is not
|
||||
//required for the initiator of the close to wait for the responding
|
||||
//close_notify alert before closing the read side of the connection.
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
final SSLSocket client = newClient();
|
||||
|
||||
SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
|
||||
|
@ -831,6 +1012,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
// We can't forward to the client, its socket is already closed
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
@ -900,6 +1082,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
@ -953,6 +1136,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(150));
|
||||
|
@ -974,6 +1158,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(150));
|
||||
|
@ -1105,6 +1290,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
@ -1264,6 +1450,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
}
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(100));
|
||||
|
@ -1312,7 +1499,7 @@ public class SslBytesServerTest extends SslBytesTest
|
|||
// Client should close the socket, but let's hold it open.
|
||||
|
||||
// Check that we did not spin
|
||||
TimeUnit.MILLISECONDS.sleep(100);
|
||||
TimeUnit.MILLISECONDS.sleep(500);
|
||||
Assert.assertThat(sslHandles.get(), lessThan(20));
|
||||
Assert.assertThat(sslFlushes.get(), lessThan(20));
|
||||
Assert.assertThat(httpParses.get(), lessThan(50));
|
||||
|
|
|
@ -320,7 +320,7 @@ public abstract class SslBytesTest
|
|||
return latch.await(time, unit);
|
||||
}
|
||||
|
||||
public void resetServer() throws IOException
|
||||
public void sendRSTToServer() throws IOException
|
||||
{
|
||||
// Calling setSoLinger(true, 0) causes close()
|
||||
// to send a RST instead of a FIN, causing an
|
||||
|
|
|
@ -139,6 +139,12 @@ public class DeploymentManager extends AggregateLifeCycle
|
|||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the AppProviders.
|
||||
* The providers passed are added via {@link #addBean(Object)} so that
|
||||
* their lifecycles may be managed as a {@link AggregateLifeCycle}.
|
||||
* @param providers
|
||||
*/
|
||||
public void setAppProviders(Collection<AppProvider> providers)
|
||||
{
|
||||
if (isRunning())
|
||||
|
|
|
@ -5,6 +5,6 @@ contexts:MMBean: Deployed Contexts
|
|||
appProviders:MMBean: Application Providers
|
||||
getApps(java.lang.String):MBean:ACTION: List apps that are located at specified App LifeCycle node
|
||||
getApps(java.lang.String)[0]:nodeName: Name of the App LifeCycle node
|
||||
requestAppGoal(java.lang.String,java.lang.String) ACTION: Request the app to be moved to the specified App LifeCycle node
|
||||
requestAppGoal(java.lang.String,java.lang.String):ACTION: Request the app to be moved to the specified App LifeCycle node
|
||||
requestAppGoal(java.lang.String,java.lang.String)[0]:appId:App identifier
|
||||
requestAppGoal(java.lang.String,java.lang.String)[1]:nodeName:Name of the App LifeCycle node
|
||||
requestAppGoal(java.lang.String,java.lang.String)[1]:nodeName:Name of the App LifeCycle node
|
||||
|
|
|
@ -111,6 +111,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.copyWebapp("foo-webapp-1.war","foo.war");
|
||||
jetty.copyContext("foo.xml","foo.xml");
|
||||
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
@ -125,12 +126,14 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.copyWebapp("foo-webapp-1.war","foo.war");
|
||||
jetty.copyContext("foo.xml","foo.xml");
|
||||
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
||||
jetty.removeContext("foo.xml");
|
||||
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
// FIXME: hot undeploy with removal not working! - jetty.assertNoWebAppContexts();
|
||||
|
@ -151,6 +154,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
jetty.copyWebapp("foo-webapp-1.war","foo.war");
|
||||
jetty.copyContext("foo.xml","foo.xml");
|
||||
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
@ -165,6 +169,7 @@ public class ScanningAppProviderRuntimeUpdatesTest
|
|||
|
||||
// This should result in the existing foo.war being replaced with the new foo.war
|
||||
waitForDirectoryScan();
|
||||
waitForDirectoryScan();
|
||||
jetty.assertWebAppContextsExists("/foo");
|
||||
|
||||
// Test that webapp response contains "-2"
|
||||
|
|
|
@ -31,6 +31,14 @@
|
|||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.6</source>
|
||||
<target>1.6</target>
|
||||
<verbose>false</verbose>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.felix</groupId>
|
||||
<artifactId>maven-bundle-plugin</artifactId>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<version>8.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-http</artifactId>
|
||||
<name>Jetty :: Http Utility</name>
|
||||
<properties>
|
||||
|
|
|
@ -19,211 +19,85 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
|||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Abstract Buffer pool.
|
||||
* simple unbounded pool of buffers for header, request and response sizes.
|
||||
*
|
||||
*/
|
||||
public class HttpBuffers extends AbstractLifeCycle
|
||||
public interface HttpBuffers
|
||||
{
|
||||
private int _requestBufferSize=16*1024;
|
||||
private int _requestHeaderSize=6*1024;
|
||||
private int _responseBufferSize=32*1024;
|
||||
private int _responseHeaderSize=6*1024;
|
||||
private int _maxBuffers=1024;
|
||||
|
||||
private Buffers.Type _requestBufferType=Buffers.Type.BYTE_ARRAY;
|
||||
private Buffers.Type _requestHeaderType=Buffers.Type.BYTE_ARRAY;
|
||||
private Buffers.Type _responseBufferType=Buffers.Type.BYTE_ARRAY;
|
||||
private Buffers.Type _responseHeaderType=Buffers.Type.BYTE_ARRAY;
|
||||
|
||||
private Buffers _requestBuffers;
|
||||
private Buffers _responseBuffers;
|
||||
|
||||
|
||||
public HttpBuffers()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the requestBufferSize
|
||||
*/
|
||||
public int getRequestBufferSize()
|
||||
{
|
||||
return _requestBufferSize;
|
||||
}
|
||||
public int getRequestBufferSize();
|
||||
|
||||
/**
|
||||
* @param requestBufferSize the requestBufferSize to set
|
||||
*/
|
||||
public void setRequestBufferSize(int requestBufferSize)
|
||||
{
|
||||
_requestBufferSize = requestBufferSize;
|
||||
}
|
||||
public void setRequestBufferSize(int requestBufferSize);
|
||||
|
||||
/**
|
||||
* @return the requestHeaderSize
|
||||
*/
|
||||
public int getRequestHeaderSize()
|
||||
{
|
||||
return _requestHeaderSize;
|
||||
}
|
||||
public int getRequestHeaderSize();
|
||||
|
||||
/**
|
||||
* @param requestHeaderSize the requestHeaderSize to set
|
||||
*/
|
||||
public void setRequestHeaderSize(int requestHeaderSize)
|
||||
{
|
||||
_requestHeaderSize = requestHeaderSize;
|
||||
}
|
||||
public void setRequestHeaderSize(int requestHeaderSize);
|
||||
|
||||
/**
|
||||
* @return the responseBufferSize
|
||||
*/
|
||||
public int getResponseBufferSize()
|
||||
{
|
||||
return _responseBufferSize;
|
||||
}
|
||||
public int getResponseBufferSize();
|
||||
|
||||
/**
|
||||
* @param responseBufferSize the responseBufferSize to set
|
||||
*/
|
||||
public void setResponseBufferSize(int responseBufferSize)
|
||||
{
|
||||
_responseBufferSize = responseBufferSize;
|
||||
}
|
||||
public void setResponseBufferSize(int responseBufferSize);
|
||||
|
||||
/**
|
||||
* @return the responseHeaderSize
|
||||
*/
|
||||
public int getResponseHeaderSize()
|
||||
{
|
||||
return _responseHeaderSize;
|
||||
}
|
||||
public int getResponseHeaderSize();
|
||||
|
||||
/**
|
||||
* @param responseHeaderSize the responseHeaderSize to set
|
||||
*/
|
||||
public void setResponseHeaderSize(int responseHeaderSize)
|
||||
{
|
||||
_responseHeaderSize = responseHeaderSize;
|
||||
}
|
||||
public void setResponseHeaderSize(int responseHeaderSize);
|
||||
|
||||
/**
|
||||
* @return the requestBufferType
|
||||
*/
|
||||
public Buffers.Type getRequestBufferType()
|
||||
{
|
||||
return _requestBufferType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requestBufferType the requestBufferType to set
|
||||
*/
|
||||
protected void setRequestBufferType(Buffers.Type requestBufferType)
|
||||
{
|
||||
_requestBufferType = requestBufferType;
|
||||
}
|
||||
public Buffers.Type getRequestBufferType();
|
||||
|
||||
/**
|
||||
* @return the requestHeaderType
|
||||
*/
|
||||
public Buffers.Type getRequestHeaderType()
|
||||
{
|
||||
return _requestHeaderType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requestHeaderType the requestHeaderType to set
|
||||
*/
|
||||
protected void setRequestHeaderType(Buffers.Type requestHeaderType)
|
||||
{
|
||||
_requestHeaderType = requestHeaderType;
|
||||
}
|
||||
public Buffers.Type getRequestHeaderType();
|
||||
|
||||
/**
|
||||
* @return the responseBufferType
|
||||
*/
|
||||
public Buffers.Type getResponseBufferType()
|
||||
{
|
||||
return _responseBufferType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param responseBufferType the responseBufferType to set
|
||||
*/
|
||||
protected void setResponseBufferType(Buffers.Type responseBufferType)
|
||||
{
|
||||
_responseBufferType = responseBufferType;
|
||||
}
|
||||
public Buffers.Type getResponseBufferType();
|
||||
|
||||
/**
|
||||
* @return the responseHeaderType
|
||||
*/
|
||||
public Buffers.Type getResponseHeaderType()
|
||||
{
|
||||
return _responseHeaderType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param responseHeaderType the responseHeaderType to set
|
||||
*/
|
||||
protected void setResponseHeaderType(Buffers.Type responseHeaderType)
|
||||
{
|
||||
_responseHeaderType = responseHeaderType;
|
||||
}
|
||||
public Buffers.Type getResponseHeaderType();
|
||||
|
||||
/**
|
||||
* @param requestBuffers the requestBuffers to set
|
||||
*/
|
||||
public void setRequestBuffers(Buffers requestBuffers)
|
||||
{
|
||||
_requestBuffers = requestBuffers;
|
||||
}
|
||||
public void setRequestBuffers(Buffers requestBuffers);
|
||||
|
||||
/**
|
||||
* @param responseBuffers the responseBuffers to set
|
||||
*/
|
||||
public void setResponseBuffers(Buffers responseBuffers)
|
||||
{
|
||||
_responseBuffers = responseBuffers;
|
||||
}
|
||||
public void setResponseBuffers(Buffers responseBuffers);
|
||||
|
||||
@Override
|
||||
protected void doStart()
|
||||
throws Exception
|
||||
{
|
||||
_requestBuffers=BuffersFactory.newBuffers(_requestHeaderType,_requestHeaderSize,_requestBufferType,_requestBufferSize,_requestBufferType,getMaxBuffers());
|
||||
_responseBuffers=BuffersFactory.newBuffers(_responseHeaderType,_responseHeaderSize,_responseBufferType,_responseBufferSize,_responseBufferType,getMaxBuffers());
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop()
|
||||
throws Exception
|
||||
{
|
||||
_requestBuffers=null;
|
||||
_responseBuffers=null;
|
||||
}
|
||||
public Buffers getRequestBuffers();
|
||||
|
||||
public Buffers getRequestBuffers()
|
||||
{
|
||||
return _requestBuffers;
|
||||
}
|
||||
|
||||
public Buffers getResponseBuffers();
|
||||
|
||||
public Buffers getResponseBuffers()
|
||||
{
|
||||
return _responseBuffers;
|
||||
}
|
||||
public void setMaxBuffers(int maxBuffers);
|
||||
|
||||
public void setMaxBuffers(int maxBuffers)
|
||||
{
|
||||
_maxBuffers = maxBuffers;
|
||||
}
|
||||
|
||||
public int getMaxBuffers()
|
||||
{
|
||||
return _maxBuffers;
|
||||
}
|
||||
public int getMaxBuffers();
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,233 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2004-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.http;
|
||||
|
||||
import org.eclipse.jetty.io.Buffers;
|
||||
import org.eclipse.jetty.io.BuffersFactory;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Abstract Buffer pool.
|
||||
* simple unbounded pool of buffers for header, request and response sizes.
|
||||
*
|
||||
*/
|
||||
public class HttpBuffersImpl extends AbstractLifeCycle implements HttpBuffers
|
||||
{
|
||||
private int _requestBufferSize=16*1024;
|
||||
private int _requestHeaderSize=6*1024;
|
||||
private int _responseBufferSize=32*1024;
|
||||
private int _responseHeaderSize=6*1024;
|
||||
private int _maxBuffers=1024;
|
||||
|
||||
private Buffers.Type _requestBufferType=Buffers.Type.BYTE_ARRAY;
|
||||
private Buffers.Type _requestHeaderType=Buffers.Type.BYTE_ARRAY;
|
||||
private Buffers.Type _responseBufferType=Buffers.Type.BYTE_ARRAY;
|
||||
private Buffers.Type _responseHeaderType=Buffers.Type.BYTE_ARRAY;
|
||||
|
||||
private Buffers _requestBuffers;
|
||||
private Buffers _responseBuffers;
|
||||
|
||||
|
||||
public HttpBuffersImpl()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the requestBufferSize
|
||||
*/
|
||||
public int getRequestBufferSize()
|
||||
{
|
||||
return _requestBufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requestBufferSize the requestBufferSize to set
|
||||
*/
|
||||
public void setRequestBufferSize(int requestBufferSize)
|
||||
{
|
||||
_requestBufferSize = requestBufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the requestHeaderSize
|
||||
*/
|
||||
public int getRequestHeaderSize()
|
||||
{
|
||||
return _requestHeaderSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requestHeaderSize the requestHeaderSize to set
|
||||
*/
|
||||
public void setRequestHeaderSize(int requestHeaderSize)
|
||||
{
|
||||
_requestHeaderSize = requestHeaderSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the responseBufferSize
|
||||
*/
|
||||
public int getResponseBufferSize()
|
||||
{
|
||||
return _responseBufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param responseBufferSize the responseBufferSize to set
|
||||
*/
|
||||
public void setResponseBufferSize(int responseBufferSize)
|
||||
{
|
||||
_responseBufferSize = responseBufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the responseHeaderSize
|
||||
*/
|
||||
public int getResponseHeaderSize()
|
||||
{
|
||||
return _responseHeaderSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param responseHeaderSize the responseHeaderSize to set
|
||||
*/
|
||||
public void setResponseHeaderSize(int responseHeaderSize)
|
||||
{
|
||||
_responseHeaderSize = responseHeaderSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the requestBufferType
|
||||
*/
|
||||
public Buffers.Type getRequestBufferType()
|
||||
{
|
||||
return _requestBufferType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requestBufferType the requestBufferType to set
|
||||
*/
|
||||
public void setRequestBufferType(Buffers.Type requestBufferType)
|
||||
{
|
||||
_requestBufferType = requestBufferType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the requestHeaderType
|
||||
*/
|
||||
public Buffers.Type getRequestHeaderType()
|
||||
{
|
||||
return _requestHeaderType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requestHeaderType the requestHeaderType to set
|
||||
*/
|
||||
public void setRequestHeaderType(Buffers.Type requestHeaderType)
|
||||
{
|
||||
_requestHeaderType = requestHeaderType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the responseBufferType
|
||||
*/
|
||||
public Buffers.Type getResponseBufferType()
|
||||
{
|
||||
return _responseBufferType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param responseBufferType the responseBufferType to set
|
||||
*/
|
||||
public void setResponseBufferType(Buffers.Type responseBufferType)
|
||||
{
|
||||
_responseBufferType = responseBufferType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the responseHeaderType
|
||||
*/
|
||||
public Buffers.Type getResponseHeaderType()
|
||||
{
|
||||
return _responseHeaderType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param responseHeaderType the responseHeaderType to set
|
||||
*/
|
||||
public void setResponseHeaderType(Buffers.Type responseHeaderType)
|
||||
{
|
||||
_responseHeaderType = responseHeaderType;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param requestBuffers the requestBuffers to set
|
||||
*/
|
||||
public void setRequestBuffers(Buffers requestBuffers)
|
||||
{
|
||||
_requestBuffers = requestBuffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param responseBuffers the responseBuffers to set
|
||||
*/
|
||||
public void setResponseBuffers(Buffers responseBuffers)
|
||||
{
|
||||
_responseBuffers = responseBuffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart()
|
||||
throws Exception
|
||||
{
|
||||
_requestBuffers=BuffersFactory.newBuffers(_requestHeaderType,_requestHeaderSize,_requestBufferType,_requestBufferSize,_requestBufferType,getMaxBuffers());
|
||||
_responseBuffers=BuffersFactory.newBuffers(_responseHeaderType,_responseHeaderSize,_responseBufferType,_responseBufferSize,_responseBufferType,getMaxBuffers());
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop()
|
||||
throws Exception
|
||||
{
|
||||
_requestBuffers=null;
|
||||
_responseBuffers=null;
|
||||
}
|
||||
|
||||
public Buffers getRequestBuffers()
|
||||
{
|
||||
return _requestBuffers;
|
||||
}
|
||||
|
||||
|
||||
public Buffers getResponseBuffers()
|
||||
{
|
||||
return _responseBuffers;
|
||||
}
|
||||
|
||||
public void setMaxBuffers(int maxBuffers)
|
||||
{
|
||||
_maxBuffers = maxBuffers;
|
||||
}
|
||||
|
||||
public int getMaxBuffers()
|
||||
{
|
||||
return _maxBuffers;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return _requestBuffers+"/"+_responseBuffers;
|
||||
}
|
||||
}
|
|
@ -146,7 +146,16 @@ public class PathMap extends HashMap implements Externalizable
|
|||
@Override
|
||||
public Object put(Object pathSpec, Object object)
|
||||
{
|
||||
StringTokenizer tok = new StringTokenizer(pathSpec.toString(),__pathSpecSeparators);
|
||||
String str = pathSpec.toString();
|
||||
if ("".equals(str.trim()))
|
||||
{
|
||||
Entry entry = new Entry("",object);
|
||||
entry.setMapped("");
|
||||
_exactMap.put("", entry);
|
||||
return super.put("", object);
|
||||
}
|
||||
|
||||
StringTokenizer tok = new StringTokenizer(str,__pathSpecSeparators);
|
||||
Object old =null;
|
||||
|
||||
while (tok.hasMoreTokens())
|
||||
|
@ -218,13 +227,21 @@ public class PathMap extends HashMap implements Externalizable
|
|||
*/
|
||||
public Entry getMatch(String path)
|
||||
{
|
||||
Map.Entry entry;
|
||||
Map.Entry entry=null;
|
||||
|
||||
if (path==null)
|
||||
return null;
|
||||
|
||||
int l=path.length();
|
||||
|
||||
|
||||
//special case
|
||||
if (l == 1 && path.charAt(0)=='/')
|
||||
{
|
||||
entry = (Map.Entry)_exactMap.get("");
|
||||
if (entry != null)
|
||||
return (Entry)entry;
|
||||
}
|
||||
|
||||
// try exact match
|
||||
entry=_exactMap.getEntry(path,0,l);
|
||||
if (entry!=null)
|
||||
|
@ -455,6 +472,9 @@ public class PathMap extends HashMap implements Externalizable
|
|||
*/
|
||||
public static String pathInfo(String pathSpec, String path)
|
||||
{
|
||||
if ("".equals(pathSpec))
|
||||
return path; //servlet 3 spec sec 12.2 will be '/'
|
||||
|
||||
char c = pathSpec.charAt(0);
|
||||
|
||||
if (c=='/')
|
||||
|
|
|
@ -36,6 +36,7 @@ public class PathMapTest extends TestCase
|
|||
p.put("*.gz", "7");
|
||||
p.put("/", "8");
|
||||
p.put("/XXX:/YYY", "9");
|
||||
p.put("", "10");
|
||||
|
||||
String[][] tests = {
|
||||
{ "/abs/path", "1"},
|
||||
|
@ -68,7 +69,7 @@ public class PathMapTest extends TestCase
|
|||
assertEquals("Dir matches", "[/animal/fish/*=4, /animal/*=5, /=8]", p.getMatches("/animal/fish/").toString());
|
||||
assertEquals("Dir matches", "[/animal/fish/*=4, /animal/*=5, /=8]", p.getMatches("/animal/fish").toString());
|
||||
assertEquals("Dir matches", "[/=8]", p.getMatches("/").toString());
|
||||
assertEquals("Dir matches", "[/=8]", p.getMatches("").toString());
|
||||
assertEquals("Dir matches", "[=10, /=8]", p.getMatches("").toString());
|
||||
|
||||
assertEquals("pathMatch exact", "/Foo/bar", PathMap.pathMatch("/Foo/bar", "/Foo/bar"));
|
||||
assertEquals("pathMatch prefix", "/Foo", PathMap.pathMatch("/Foo/*", "/Foo/bar"));
|
||||
|
@ -125,6 +126,8 @@ public class PathMapTest extends TestCase
|
|||
assertTrue("!match /foo/*", !PathMap.match("/foo/*", "/bar/anything"));
|
||||
assertTrue("match *.foo", PathMap.match("*.foo", "anything.foo"));
|
||||
assertTrue("!match *.foo", !PathMap.match("*.foo", "anything.bar"));
|
||||
|
||||
assertEquals("match / with ''", "10", p.getMatch("/").getValue());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<version>8.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
<name>Jetty :: IO Utility</name>
|
||||
<properties>
|
||||
|
|
|
@ -58,7 +58,7 @@ public abstract class AbstractBuffers implements Buffers
|
|||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Create a new content Buffer
|
||||
|
@ -77,7 +77,7 @@ public abstract class AbstractBuffers implements Buffers
|
|||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Create a new content Buffer
|
||||
|
@ -142,4 +142,9 @@ public abstract class AbstractBuffers implements Buffers
|
|||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
/* ------------------------------------------------------------ */
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s [%d,%d]", getClass().getSimpleName(), _headerSize, _bufferSize);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ public class PooledBuffers extends AbstractBuffers
|
|||
_otherBuffers=bufferType==otherType;
|
||||
_maxSize=maxSize;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public Buffer getHeader()
|
||||
{
|
||||
|
@ -55,17 +55,17 @@ public class PooledBuffers extends AbstractBuffers
|
|||
return getHeader();
|
||||
if (_otherBuffers && size==getBufferSize())
|
||||
return getBuffer();
|
||||
|
||||
|
||||
// Look for an other buffer
|
||||
Buffer buffer = _others.poll();
|
||||
|
||||
|
||||
// consume all other buffers until one of the right size is found
|
||||
while (buffer!=null && buffer.capacity()!=size)
|
||||
{
|
||||
_size.decrementAndGet();
|
||||
buffer = _others.poll();
|
||||
}
|
||||
|
||||
|
||||
if (buffer==null)
|
||||
buffer=newBuffer(size);
|
||||
else
|
||||
|
@ -89,7 +89,16 @@ public class PooledBuffers extends AbstractBuffers
|
|||
else if (isBuffer(buffer))
|
||||
_buffers.add(buffer);
|
||||
else
|
||||
_others.add(buffer);
|
||||
_others.add(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return String.format("%s [%d/%d@%d,%d/%d@%d,%d/%d@-]",
|
||||
getClass().getSimpleName(),
|
||||
_headers.size(),_maxSize,_headerSize,
|
||||
_buffers.size(),_maxSize,_bufferSize,
|
||||
_others.size(),_maxSize);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -246,8 +246,7 @@ public class ChannelEndPoint implements EndPoint
|
|||
}
|
||||
catch (IOException x)
|
||||
{
|
||||
LOG.debug(x.toString());
|
||||
LOG.ignore(x);
|
||||
LOG.debug("Exception while filling", x);
|
||||
try
|
||||
{
|
||||
if (_channel.isOpen())
|
||||
|
|
|
@ -260,7 +260,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
for (int i=0;i<getSelectSets();i++)
|
||||
{
|
||||
final int id=i;
|
||||
dispatch(new Runnable()
|
||||
boolean selecting=dispatch(new Runnable()
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
|
@ -303,6 +303,9 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
}
|
||||
|
||||
});
|
||||
|
||||
if (!selecting)
|
||||
throw new IllegalStateException("!Selecting");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -957,6 +960,7 @@ public abstract class SelectorManager extends AbstractLifeCycle implements Dumpa
|
|||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
|
||||
AggregateLifeCycle.dump(out,indent,dump);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -541,6 +541,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
switch(result.getStatus())
|
||||
{
|
||||
case BUFFER_UNDERFLOW:
|
||||
if (_endp.isInputShutdown())
|
||||
_inbound.clear();
|
||||
break;
|
||||
|
||||
case BUFFER_OVERFLOW:
|
||||
|
@ -598,7 +600,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection
|
|||
{
|
||||
return _engine;
|
||||
}
|
||||
|
||||
|
||||
public AsyncEndPoint getEndpoint()
|
||||
{
|
||||
return _aEndp;
|
||||
|
|
|
@ -42,36 +42,38 @@ import org.eclipse.jetty.server.Authentication.User;
|
|||
public class JaspiAuthenticator implements Authenticator
|
||||
{
|
||||
private final ServerAuthConfig _authConfig;
|
||||
|
||||
private final Map _authProperties;
|
||||
|
||||
private final ServletCallbackHandler _callbackHandler;
|
||||
|
||||
private final Subject _serviceSubject;
|
||||
|
||||
private final boolean _allowLazyAuthentication;
|
||||
|
||||
private final IdentityService _identityService;
|
||||
|
||||
private final DeferredAuthentication _deferred;
|
||||
|
||||
public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler,
|
||||
Subject serviceSubject, boolean allowLazyAuthentication, IdentityService identityService)
|
||||
public JaspiAuthenticator(ServerAuthConfig authConfig, Map authProperties, ServletCallbackHandler callbackHandler, Subject serviceSubject,
|
||||
boolean allowLazyAuthentication, IdentityService identityService)
|
||||
{
|
||||
// TODO maybe pass this in via setConfiguration ?
|
||||
if (callbackHandler == null)
|
||||
throw new NullPointerException("No CallbackHandler");
|
||||
if (authConfig == null)
|
||||
throw new NullPointerException("No AuthConfig");
|
||||
if (callbackHandler == null) throw new NullPointerException("No CallbackHandler");
|
||||
if (authConfig == null) throw new NullPointerException("No AuthConfig");
|
||||
this._authConfig = authConfig;
|
||||
this._authProperties = authProperties;
|
||||
this._callbackHandler = callbackHandler;
|
||||
this._serviceSubject = serviceSubject;
|
||||
this._allowLazyAuthentication = allowLazyAuthentication;
|
||||
this._identityService = identityService;
|
||||
this._deferred=new DeferredAuthentication(this);
|
||||
this._deferred = new DeferredAuthentication(this);
|
||||
}
|
||||
|
||||
|
||||
public void setConfiguration(AuthConfiguration configuration)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getAuthMethod()
|
||||
{
|
||||
return "JASPI";
|
||||
|
@ -79,56 +81,57 @@ public class JaspiAuthenticator implements Authenticator
|
|||
|
||||
public Authentication validateRequest(ServletRequest request, ServletResponse response, boolean mandatory) throws ServerAuthException
|
||||
{
|
||||
if (_allowLazyAuthentication && !mandatory)
|
||||
return _deferred;
|
||||
|
||||
JaspiMessageInfo info = new JaspiMessageInfo(request, response, mandatory);
|
||||
request.setAttribute("org.eclipse.jetty.security.jaspi.info",info);
|
||||
return validateRequest(info);
|
||||
request.setAttribute("org.eclipse.jetty.security.jaspi.info", info);
|
||||
|
||||
Authentication a = validateRequest(info);
|
||||
|
||||
//if its not mandatory to authenticate, and the authenticator returned UNAUTHENTICATED, we treat it as authentication deferred
|
||||
if (_allowLazyAuthentication && !info.isAuthMandatory() && a == Authentication.UNAUTHENTICATED)
|
||||
a =_deferred;
|
||||
return a;
|
||||
}
|
||||
|
||||
// most likely validatedUser is not needed here.
|
||||
public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
|
||||
{
|
||||
JaspiMessageInfo info = (JaspiMessageInfo)req.getAttribute("org.eclipse.jetty.security.jaspi.info");
|
||||
if (info==null) throw new NullPointerException("MeesageInfo from request missing: " + req);
|
||||
return secureResponse(info,validatedUser);
|
||||
JaspiMessageInfo info = (JaspiMessageInfo) req.getAttribute("org.eclipse.jetty.security.jaspi.info");
|
||||
if (info == null) throw new NullPointerException("MessageInfo from request missing: " + req);
|
||||
return secureResponse(info, validatedUser);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public Authentication validateRequest(JaspiMessageInfo messageInfo) throws ServerAuthException
|
||||
{
|
||||
try
|
||||
{
|
||||
String authContextId = _authConfig.getAuthContextID(messageInfo);
|
||||
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId,_serviceSubject,_authProperties);
|
||||
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties);
|
||||
Subject clientSubject = new Subject();
|
||||
|
||||
AuthStatus authStatus = authContext.validateRequest(messageInfo,clientSubject,_serviceSubject);
|
||||
// String authMethod = (String)messageInfo.getMap().get(JaspiMessageInfo.AUTH_METHOD_KEY);
|
||||
AuthStatus authStatus = authContext.validateRequest(messageInfo, clientSubject, _serviceSubject);
|
||||
|
||||
if (authStatus == AuthStatus.SEND_CONTINUE) return Authentication.SEND_CONTINUE;
|
||||
if (authStatus == AuthStatus.SEND_FAILURE) return Authentication.SEND_FAILURE;
|
||||
|
||||
if (authStatus == AuthStatus.SEND_CONTINUE)
|
||||
return Authentication.SEND_CONTINUE;
|
||||
if (authStatus == AuthStatus.SEND_FAILURE)
|
||||
return Authentication.SEND_FAILURE;
|
||||
|
||||
if (authStatus == AuthStatus.SUCCESS)
|
||||
{
|
||||
Set<UserIdentity> ids = clientSubject.getPrivateCredentials(UserIdentity.class);
|
||||
Set<UserIdentity> ids = clientSubject.getPrivateCredentials(UserIdentity.class);
|
||||
UserIdentity userIdentity;
|
||||
if (ids.size() > 0)
|
||||
{
|
||||
userIdentity = ids.iterator().next();
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
CallerPrincipalCallback principalCallback = _callbackHandler.getThreadCallerPrincipalCallback();
|
||||
if (principalCallback == null)
|
||||
{
|
||||
return Authentication.UNAUTHENTICATED;
|
||||
}
|
||||
if (principalCallback == null) { return Authentication.UNAUTHENTICATED; }
|
||||
Principal principal = principalCallback.getPrincipal();
|
||||
if (principal == null) {
|
||||
if (principal == null)
|
||||
{
|
||||
String principalName = principalCallback.getName();
|
||||
Set<Principal> principals = principalCallback.getSubject().getPrincipals();
|
||||
for (Principal p: principals)
|
||||
for (Principal p : principals)
|
||||
{
|
||||
if (p.getName().equals(principalName))
|
||||
{
|
||||
|
@ -136,10 +139,7 @@ public class JaspiAuthenticator implements Authenticator
|
|||
break;
|
||||
}
|
||||
}
|
||||
if (principal == null)
|
||||
{
|
||||
return Authentication.UNAUTHENTICATED;
|
||||
}
|
||||
if (principal == null) { return Authentication.UNAUTHENTICATED; }
|
||||
}
|
||||
GroupPrincipalCallback groupPrincipalCallback = _callbackHandler.getThreadGroupPrincipalCallback();
|
||||
String[] groups = groupPrincipalCallback == null ? null : groupPrincipalCallback.getGroups();
|
||||
|
@ -149,10 +149,10 @@ public class JaspiAuthenticator implements Authenticator
|
|||
}
|
||||
if (authStatus == AuthStatus.SEND_SUCCESS)
|
||||
{
|
||||
//we are processing a message in a secureResponse dialog.
|
||||
// we are processing a message in a secureResponse dialog.
|
||||
return Authentication.SEND_SUCCESS;
|
||||
}
|
||||
//should not happen
|
||||
// should not happen
|
||||
throw new NullPointerException("No AuthStatus returned");
|
||||
}
|
||||
catch (AuthException e)
|
||||
|
@ -166,9 +166,10 @@ public class JaspiAuthenticator implements Authenticator
|
|||
try
|
||||
{
|
||||
String authContextId = _authConfig.getAuthContextID(messageInfo);
|
||||
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId,_serviceSubject,_authProperties);
|
||||
// TODO authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject());
|
||||
AuthStatus status = authContext.secureResponse(messageInfo,_serviceSubject);
|
||||
ServerAuthContext authContext = _authConfig.getAuthContext(authContextId, _serviceSubject, _authProperties);
|
||||
// TODO
|
||||
// authContext.cleanSubject(messageInfo,validatedUser.getUserIdentity().getSubject());
|
||||
AuthStatus status = authContext.secureResponse(messageInfo, _serviceSubject);
|
||||
return (AuthStatus.SEND_SUCCESS.equals(status));
|
||||
}
|
||||
catch (AuthException e)
|
||||
|
|
|
@ -97,10 +97,10 @@ public class JaspiAuthenticatorFactory extends DefaultAuthenticatorFactory
|
|||
|
||||
Subject serviceSubject=findServiceSubject(server);
|
||||
String serverName=findServerName(server,serviceSubject);
|
||||
|
||||
|
||||
String appContext = serverName + " " + context.getContextPath();
|
||||
|
||||
AuthConfigProvider authConfigProvider = authConfigFactory.getConfigProvider(MESSAGE_LAYER,appContext,listener);
|
||||
|
||||
if (authConfigProvider != null)
|
||||
{
|
||||
ServletCallbackHandler servletCallbackHandler = new ServletCallbackHandler(loginService);
|
||||
|
|
|
@ -90,8 +90,9 @@ public class ServletCallbackHandler implements CallbackHandler
|
|||
|
||||
if (user!=null)
|
||||
{
|
||||
loginCallback.setUserPrincipal(user.getUserPrincipal());
|
||||
credentialValidationCallback.getSubject().getPrivateCredentials().add(loginCallback);
|
||||
credentialValidationCallback.setResult(true);
|
||||
|
||||
credentialValidationCallback.getSubject().getPrincipals().addAll(user.getSubject().getPrincipals());
|
||||
credentialValidationCallback.getSubject().getPrivateCredentials().add(user);
|
||||
}
|
||||
|
|
|
@ -90,12 +90,12 @@ public class BaseAuthModule implements ServerAuthModule, ServerAuthContext
|
|||
public AuthStatus secureResponse(MessageInfo messageInfo, Subject serviceSubject) throws AuthException
|
||||
{
|
||||
// servlets do not need secured responses
|
||||
return AuthStatus.SUCCESS;
|
||||
return AuthStatus.SEND_SUCCESS;
|
||||
}
|
||||
|
||||
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException
|
||||
{
|
||||
return AuthStatus.FAILURE;
|
||||
return AuthStatus.SEND_FAILURE;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -36,7 +36,9 @@ import javax.servlet.http.HttpSessionBindingListener;
|
|||
import org.eclipse.jetty.util.security.Constraint;
|
||||
import org.eclipse.jetty.util.security.Password;
|
||||
import org.eclipse.jetty.security.CrossContextPsuedoSession;
|
||||
import org.eclipse.jetty.security.authentication.DeferredAuthentication;
|
||||
import org.eclipse.jetty.security.authentication.LoginCallbackImpl;
|
||||
import org.eclipse.jetty.server.Authentication;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.URIUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -146,37 +148,47 @@ public class FormAuthModule extends BaseAuthModule
|
|||
@Override
|
||||
public AuthStatus validateRequest(MessageInfo messageInfo, Subject clientSubject, Subject serviceSubject) throws AuthException
|
||||
{
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) messageInfo.getRequestMessage();
|
||||
HttpServletResponse response = (HttpServletResponse) messageInfo.getResponseMessage();
|
||||
HttpSession session = request.getSession(isMandatory(messageInfo));
|
||||
String uri = request.getPathInfo();
|
||||
// not mandatory and not authenticated
|
||||
if (session == null || isLoginOrErrorPage(uri)) return AuthStatus.SUCCESS;
|
||||
String uri = request.getRequestURI();
|
||||
if (uri==null)
|
||||
uri=URIUtil.SLASH;
|
||||
|
||||
boolean mandatory = isMandatory(messageInfo);
|
||||
mandatory |= isJSecurityCheck(uri);
|
||||
HttpSession session = request.getSession(mandatory);
|
||||
|
||||
// not mandatory or its the login or login error page don't authenticate
|
||||
if (!mandatory || isLoginOrErrorPage(URIUtil.addPaths(request.getServletPath(),request.getPathInfo()))) return AuthStatus.SUCCESS;
|
||||
|
||||
try
|
||||
{
|
||||
// Handle a request for authentication.
|
||||
// TODO perhaps j_securitycheck can be uri suffix?
|
||||
if (uri.endsWith(__J_SECURITY_CHECK))
|
||||
if (isJSecurityCheck(uri))
|
||||
{
|
||||
|
||||
final String username = request.getParameter(__J_USERNAME);
|
||||
final String password = request.getParameter(__J_PASSWORD);
|
||||
|
||||
boolean success = tryLogin(messageInfo, clientSubject, response, session, username, new Password(password));
|
||||
if (success)
|
||||
{
|
||||
// Redirect to original request
|
||||
String nuri = (String) session.getAttribute(__J_URI);
|
||||
// Redirect to original request
|
||||
String nuri=null;
|
||||
synchronized(session)
|
||||
{
|
||||
nuri = (String) session.getAttribute(__J_URI);
|
||||
}
|
||||
|
||||
if (nuri == null || nuri.length() == 0)
|
||||
{
|
||||
nuri = request.getContextPath();
|
||||
if (nuri.length() == 0) nuri = URIUtil.SLASH;
|
||||
if (nuri.length() == 0)
|
||||
nuri = URIUtil.SLASH;
|
||||
}
|
||||
session.removeAttribute(__J_URI); // Remove popped return
|
||||
// URI.
|
||||
response.setContentLength(0);
|
||||
|
||||
response.setContentLength(0);
|
||||
response.sendRedirect(response.encodeRedirectURL(nuri));
|
||||
|
||||
return AuthStatus.SEND_CONTINUE;
|
||||
}
|
||||
// not authenticated
|
||||
|
@ -194,95 +206,16 @@ public class FormAuthModule extends BaseAuthModule
|
|||
// that occur?
|
||||
return AuthStatus.SEND_FAILURE;
|
||||
}
|
||||
|
||||
|
||||
// Check if the session is already authenticated.
|
||||
FormCredential form_cred = (FormCredential) session.getAttribute(__J_AUTHENTICATED);
|
||||
|
||||
if (form_cred != null)
|
||||
{
|
||||
//TODO: we would like the form auth module to be able to invoke the loginservice.validate() method to check the previously authed user
|
||||
|
||||
boolean success = tryLogin(messageInfo, clientSubject, response, session, form_cred._jUserName, new Password(new String(form_cred._jPassword)));
|
||||
if (success) { return AuthStatus.SUCCESS; }
|
||||
// CallbackHandler loginCallbackHandler = new
|
||||
// UserPasswordCallbackHandler(form_cred._jUserName,
|
||||
// form_cred._jPassword);
|
||||
// LoginResult loginResult = loginService.login(clientSubject,
|
||||
// loginCallbackHandler);
|
||||
// //TODO what should happen if !isMandatory but credentials
|
||||
// exist and are wrong?
|
||||
// if (loginResult.isSuccess())
|
||||
// {
|
||||
// callbackHandler.handle(new
|
||||
// Callback[]{loginResult.getCallerPrincipalCallback(),
|
||||
// loginResult.getGroupPrincipalCallback()});
|
||||
// messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY,
|
||||
// Constraint.__FORM_AUTH);
|
||||
//
|
||||
// form_cred = new FormCredential(form_cred._jUserName,
|
||||
// form_cred._jPassword,
|
||||
// loginResult.getCallerPrincipalCallback().getPrincipal());
|
||||
//
|
||||
// session.setAttribute(__J_AUTHENTICATED, form_cred);
|
||||
// if (ssoSource != null && ssoSource.fetch(request) == null)
|
||||
// {
|
||||
// UserInfo userInfo = new UserInfo(form_cred._jUserName,
|
||||
// form_cred._jPassword);
|
||||
// ssoSource.store(userInfo, response);
|
||||
// }
|
||||
// messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY,
|
||||
// Constraint.__FORM_AUTH);
|
||||
// return AuthStatus.SUCCESS;
|
||||
// }
|
||||
|
||||
// // We have a form credential. Has it been distributed?
|
||||
// if (form_cred._userPrincipal==null)
|
||||
// {
|
||||
// // This form_cred appears to have been distributed. Need to
|
||||
// reauth
|
||||
// form_cred.authenticate(realm, request);
|
||||
//
|
||||
// // Sign-on to SSO mechanism
|
||||
// if (form_cred._userPrincipal!=null && realm instanceof
|
||||
// SSORealm)
|
||||
// ((SSORealm)realm).setSingleSignOn(request,response,form_cred._userPrincipal,new
|
||||
// Password(form_cred._jPassword));
|
||||
//
|
||||
// }
|
||||
// else if (!realm.reauthenticate(form_cred._userPrincipal))
|
||||
// // Else check that it is still authenticated.
|
||||
// form_cred._userPrincipal=null;
|
||||
//
|
||||
// // If this credential is still authenticated
|
||||
// if (form_cred._userPrincipal!=null)
|
||||
// {
|
||||
// if(LOG.isDebugEnabled())LOG.debug("FORM Authenticated for
|
||||
// "+form_cred._userPrincipal.getName());
|
||||
// request.setAuthType(Constraint.__FORM_AUTH);
|
||||
// //jaspi
|
||||
// // request.setUserPrincipal(form_cred._userPrincipal);
|
||||
// return form_cred._userPrincipal;
|
||||
// }
|
||||
// else
|
||||
// session.setAttribute(__J_AUTHENTICATED,null);
|
||||
// }
|
||||
// else if (realm instanceof SSORealm)
|
||||
// {
|
||||
// // Try a single sign on.
|
||||
// Credential cred =
|
||||
// ((SSORealm)realm).getSingleSignOn(request,response);
|
||||
//
|
||||
// if (request.getUserPrincipal()!=null)
|
||||
// {
|
||||
// form_cred=new FormCredential();
|
||||
// form_cred._userPrincipal=request.getUserPrincipal();
|
||||
// form_cred._jUserName=form_cred._userPrincipal.getName();
|
||||
// if (cred!=null)
|
||||
// form_cred._jPassword=cred.toString();
|
||||
// if(LOG.isDebugEnabled())LOG.debug("SSO for
|
||||
// "+form_cred._userPrincipal);
|
||||
//
|
||||
// request.setAuthType(Constraint.__FORM_AUTH);
|
||||
// session.setAttribute(__J_AUTHENTICATED,form_cred);
|
||||
// return form_cred._userPrincipal;
|
||||
// }
|
||||
}
|
||||
else if (ssoSource != null)
|
||||
{
|
||||
|
@ -293,19 +226,24 @@ public class FormAuthModule extends BaseAuthModule
|
|||
if (success) { return AuthStatus.SUCCESS; }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Don't authenticate authform or errorpage
|
||||
if (!isMandatory(messageInfo) || isLoginOrErrorPage(uri))
|
||||
// TODO verify this is correct action
|
||||
return AuthStatus.SUCCESS;
|
||||
// if we can't send challenge
|
||||
if (DeferredAuthentication.isDeferred(response))
|
||||
return AuthStatus.SUCCESS;
|
||||
|
||||
|
||||
// redirect to login page
|
||||
if (request.getQueryString() != null) uri += "?" + request.getQueryString();
|
||||
session.setAttribute(__J_URI, request.getScheme() + "://"
|
||||
+ request.getServerName()
|
||||
+ ":"
|
||||
+ request.getServerPort()
|
||||
+ URIUtil.addPaths(request.getContextPath(), uri));
|
||||
// redirect to login page
|
||||
StringBuffer buf = request.getRequestURL();
|
||||
if (request.getQueryString() != null)
|
||||
buf.append("?").append(request.getQueryString());
|
||||
|
||||
synchronized (session)
|
||||
{
|
||||
session.setAttribute(__J_URI, buf.toString());
|
||||
}
|
||||
|
||||
response.setContentLength(0);
|
||||
response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getContextPath(), _formLoginPage)));
|
||||
return AuthStatus.SEND_CONTINUE;
|
||||
|
@ -320,6 +258,20 @@ public class FormAuthModule extends BaseAuthModule
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public boolean isJSecurityCheck(String uri)
|
||||
{
|
||||
int jsc = uri.indexOf(__J_SECURITY_CHECK);
|
||||
|
||||
if (jsc<0)
|
||||
return false;
|
||||
int e=jsc+__J_SECURITY_CHECK.length();
|
||||
if (e==uri.length())
|
||||
return true;
|
||||
char c = uri.charAt(e);
|
||||
return c==';'||c=='#'||c=='/'||c=='?';
|
||||
}
|
||||
|
||||
private boolean tryLogin(MessageInfo messageInfo, Subject clientSubject,
|
||||
HttpServletResponse response, HttpSession session,
|
||||
|
@ -330,11 +282,11 @@ public class FormAuthModule extends BaseAuthModule
|
|||
{
|
||||
char[] pwdChars = password.toString().toCharArray();
|
||||
Set<LoginCallbackImpl> loginCallbacks = clientSubject.getPrivateCredentials(LoginCallbackImpl.class);
|
||||
|
||||
if (!loginCallbacks.isEmpty())
|
||||
{
|
||||
LoginCallbackImpl loginCallback = loginCallbacks.iterator().next();
|
||||
FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal());
|
||||
|
||||
FormCredential form_cred = new FormCredential(username, pwdChars, loginCallback.getUserPrincipal(), loginCallback.getSubject());
|
||||
session.setAttribute(__J_AUTHENTICATED, form_cred);
|
||||
}
|
||||
|
||||
|
@ -347,34 +299,6 @@ public class FormAuthModule extends BaseAuthModule
|
|||
return true;
|
||||
}
|
||||
return false;
|
||||
// LoginCallback loginCallback = new LoginCallback(clientSubject,
|
||||
// username, password);
|
||||
// loginService.login(loginCallback);
|
||||
// if (loginCallback.isSuccess())
|
||||
// {
|
||||
// CallerPrincipalCallback callerPrincipalCallback = new
|
||||
// CallerPrincipalCallback(clientSubject,
|
||||
// loginCallback.getUserPrincipal());
|
||||
// GroupPrincipalCallback groupPrincipalCallback = new
|
||||
// GroupPrincipalCallback(clientSubject,
|
||||
// loginCallback.getGroups().toArray(new
|
||||
// String[loginCallback.getGroups().size()]));
|
||||
// callbackHandler.handle(new Callback[] {callerPrincipalCallback,
|
||||
// groupPrincipalCallback});
|
||||
// messageInfo.getMap().put(JettyMessageInfo.AUTH_METHOD_KEY,
|
||||
// Constraint.__FORM_AUTH);
|
||||
// FormCredential form_cred = new FormCredential(username, password,
|
||||
// loginCallback.getUserPrincipal());
|
||||
//
|
||||
// session.setAttribute(__J_AUTHENTICATED, form_cred);
|
||||
// // Sign-on to SSO mechanism
|
||||
// if (ssoSource != null)
|
||||
// {
|
||||
// UserInfo userInfo = new UserInfo(username, password);
|
||||
// ssoSource.store(userInfo, response);
|
||||
// }
|
||||
// }
|
||||
// return loginCallback.isSuccess();
|
||||
}
|
||||
|
||||
public boolean isLoginOrErrorPage(String pathInContext)
|
||||
|
@ -393,12 +317,15 @@ public class FormAuthModule extends BaseAuthModule
|
|||
char[] _jPassword;
|
||||
|
||||
transient Principal _userPrincipal;
|
||||
|
||||
transient Subject _subject;
|
||||
|
||||
private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal)
|
||||
private FormCredential(String _jUserName, char[] _jPassword, Principal _userPrincipal, Subject subject)
|
||||
{
|
||||
this._jUserName = _jUserName;
|
||||
this._jPassword = _jPassword;
|
||||
this._userPrincipal = _userPrincipal;
|
||||
this._subject = subject;
|
||||
}
|
||||
|
||||
public void valueBound(HttpSessionBindingEvent event)
|
||||
|
|
|
@ -30,34 +30,28 @@
|
|||
<!-- Initialize the Jetty MBean container -->
|
||||
<!-- =========================================================== -->
|
||||
<New id="MBeanContainer" class="org.eclipse.jetty.jmx.MBeanContainer">
|
||||
<Arg>
|
||||
<Ref id="MBeanServer" />
|
||||
</Arg>
|
||||
<Arg><Ref id="MBeanServer" /></Arg>
|
||||
<Call name="start"/>
|
||||
</New>
|
||||
|
||||
<!-- Add to the Server to listen for object events -->
|
||||
<Get id="Container" name="container">
|
||||
<Call name="addEventListener">
|
||||
<Arg>
|
||||
<Ref id="MBeanContainer" />
|
||||
</Arg>
|
||||
<Arg><Ref id="MBeanContainer" /></Arg>
|
||||
</Call>
|
||||
</Get>
|
||||
|
||||
<!-- Add to the Server as a lifecycle -->
|
||||
<!-- Only do this if you know you will only have a single jetty server -->
|
||||
<!-- Add to the Server as a managed lifecycle -->
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<Ref id="MBeanContainer" />
|
||||
</Arg>
|
||||
<Arg><Ref id="MBeanContainer"/></Arg>
|
||||
<Arg type="boolean">true</Arg>
|
||||
</Call>
|
||||
|
||||
<!-- Add the static log -->
|
||||
<Get id="Logger" class="org.eclipse.jetty.util.log.Log" name="log" />
|
||||
<Ref id="MBeanContainer">
|
||||
<Call name="addBean">
|
||||
<Arg>
|
||||
<Ref id="Logger" />
|
||||
<New class="org.eclipse.jetty.util.log.Log"/>
|
||||
</Arg>
|
||||
</Call>
|
||||
</Ref>
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.eclipse.jetty.util.component.Container.Relationship;
|
|||
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.log.StdErrLog;
|
||||
import org.eclipse.jetty.util.thread.ShutdownThread;
|
||||
|
||||
/**
|
||||
|
@ -86,15 +87,6 @@ public class MBeanContainer extends AbstractLifeCycle implements Container.Liste
|
|||
public MBeanContainer(MBeanServer server)
|
||||
{
|
||||
_server = server;
|
||||
|
||||
try
|
||||
{
|
||||
start();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.ignore(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.util.log.jmx;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.jmx.ObjectMBean;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class LogMBean extends ObjectMBean
|
||||
{
|
||||
|
||||
public LogMBean(Object managedObject)
|
||||
{
|
||||
super(managedObject);
|
||||
}
|
||||
|
||||
public List<String> getLoggers()
|
||||
{
|
||||
List<String> keySet = new ArrayList<String>(Log.getLoggers().keySet());
|
||||
return keySet;
|
||||
}
|
||||
|
||||
public boolean isDebugEnabled(String logger)
|
||||
{
|
||||
return Log.getLogger(logger).isDebugEnabled();
|
||||
}
|
||||
|
||||
public void setDebugEnabled(String logger, Boolean enabled)
|
||||
{
|
||||
Log.getLogger(logger).setDebugEnabled(enabled);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
Log: Jetty Logging implementaton
|
||||
loggers:MBean: List of all instantiated loggers
|
||||
debugEnabled:RW: True if debug enabled for root logger Log.LOG
|
||||
isDebugEnabled(java.lang.String):MBean:INFO: True if debug is enabled for the given logger
|
||||
isDebugEnabled(java.lang.String)[0]:loggerName: Name of the logger to return isDebugEnabled for
|
||||
setDebugEnabled(java.lang.String,java.lang.Boolean):MBean:ACTION: Set debug enabled for the given logger
|
||||
setDebugEnabled(java.lang.String,java.lang.Boolean)[0]:loggerName: Name of the logger to set debug enabled
|
||||
setDebugEnabled(java.lang.String,java.lang.Boolean)[1]:enabled: true to enable debug, false otherwise
|
|
@ -1,3 +0,0 @@
|
|||
Logger: Jetty Logging implementaton
|
||||
debugEnabled: True if debug enabled
|
||||
name: Logger name
|
|
@ -1 +0,0 @@
|
|||
Slf4jLog: SL4J log adapter
|
|
@ -1 +0,0 @@
|
|||
StdErrLog: Log adapter that logs to stderr
|
|
@ -66,7 +66,6 @@
|
|||
<dependency>
|
||||
<groupId>javax.mail</groupId>
|
||||
<artifactId>mail</artifactId>
|
||||
<version>${javax-mail-version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>javax.activation</groupId>
|
||||
|
|
|
@ -457,10 +457,12 @@ public class localContextRoot implements Context
|
|||
{
|
||||
throw e;
|
||||
}
|
||||
catch (Exception e)
|
||||
catch (final Exception e)
|
||||
{
|
||||
__log.warn("",e);
|
||||
throw new NamingException (e.getMessage());
|
||||
throw new NamingException (e.getMessage())
|
||||
{
|
||||
{ initCause(e);}
|
||||
};
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
ThreadMonitor: Detect and report spinning and deadlocked threads
|
||||
|
||||
|
|
|
@ -4,17 +4,15 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.monitor;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
@ -22,7 +20,6 @@ import java.lang.management.ManagementFactory;
|
|||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import javax.management.MBeanServer;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -35,13 +32,12 @@ import org.eclipse.jetty.client.security.SimpleRealmResolver;
|
|||
import org.eclipse.jetty.http.HttpMethods;
|
||||
import org.eclipse.jetty.http.HttpStatus;
|
||||
import org.eclipse.jetty.jmx.MBeanContainer;
|
||||
import org.eclipse.jetty.monitor.JMXMonitor;
|
||||
import org.eclipse.jetty.monitor.jmx.ConsoleNotifier;
|
||||
import org.eclipse.jetty.monitor.jmx.EventNotifier;
|
||||
import org.eclipse.jetty.monitor.jmx.EventState;
|
||||
import org.eclipse.jetty.monitor.jmx.EventState.TriggerState;
|
||||
import org.eclipse.jetty.monitor.jmx.EventTrigger;
|
||||
import org.eclipse.jetty.monitor.jmx.MonitorAction;
|
||||
import org.eclipse.jetty.monitor.jmx.EventState.TriggerState;
|
||||
import org.eclipse.jetty.monitor.triggers.AndEventTrigger;
|
||||
import org.eclipse.jetty.monitor.triggers.AttrEventTrigger;
|
||||
import org.eclipse.jetty.monitor.triggers.EqualToAttrEventTrigger;
|
||||
|
@ -61,6 +57,8 @@ import org.junit.After;
|
|||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
|
@ -81,93 +79,93 @@ public class AttrEventTriggerTest
|
|||
File docRoot = new File("target/test-output/docroot/");
|
||||
docRoot.mkdirs();
|
||||
docRoot.deleteOnExit();
|
||||
|
||||
|
||||
System.setProperty("org.eclipse.jetty.util.log.DEBUG","");
|
||||
_server = new Server();
|
||||
|
||||
|
||||
SelectChannelConnector connector = new SelectChannelConnector();
|
||||
_server.addConnector(connector);
|
||||
|
||||
|
||||
_handler = new TestHandler();
|
||||
_server.setHandler(_handler);
|
||||
|
||||
|
||||
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
|
||||
MBeanContainer mBeanContainer = new MBeanContainer(mBeanServer);
|
||||
mBeanContainer.addBean(Log.getLog());
|
||||
|
||||
_counter = _handler.getRequestCounter();
|
||||
mBeanContainer.addBean(_counter);
|
||||
|
||||
_server.addBean(mBeanContainer);
|
||||
_server.getContainer().addEventListener(mBeanContainer);
|
||||
|
||||
_server.addBean(mBeanContainer, true);
|
||||
_server.getContainer().addEventListener(mBeanContainer);
|
||||
_server.start();
|
||||
|
||||
|
||||
startClient(null);
|
||||
|
||||
|
||||
_monitor = new JMXMonitor();
|
||||
|
||||
int port = _server.getConnectors()[0].getLocalPort();
|
||||
|
||||
int port = connector.getLocalPort();
|
||||
_requestUrl = "http://localhost:"+port+ "/";
|
||||
}
|
||||
|
||||
|
||||
@After
|
||||
public void tearDown()
|
||||
throws Exception
|
||||
{
|
||||
stopClient();
|
||||
|
||||
|
||||
if (_server != null)
|
||||
{
|
||||
_server.stop();
|
||||
_server = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testNoCondition()
|
||||
throws Exception
|
||||
{
|
||||
long requestCount = 10;
|
||||
|
||||
AttrEventTrigger<Long> trigger =
|
||||
|
||||
AttrEventTrigger<Long> trigger =
|
||||
new AttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter");
|
||||
|
||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet(1,requestCount);
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEqual_TRUE()
|
||||
throws Exception
|
||||
{
|
||||
long requestCount = 10;
|
||||
long testValue = 5;
|
||||
|
||||
EqualToAttrEventTrigger<Long> trigger =
|
||||
|
||||
EqualToAttrEventTrigger<Long> trigger =
|
||||
new EqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",testValue);
|
||||
|
||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet(testValue);
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEqual_FALSE()
|
||||
throws Exception
|
||||
{
|
||||
long requestCount = 10;
|
||||
long testValue = 11;
|
||||
|
||||
EqualToAttrEventTrigger<Long> trigger =
|
||||
|
||||
EqualToAttrEventTrigger<Long> trigger =
|
||||
new EqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testValue);
|
||||
|
||||
|
@ -175,19 +173,19 @@ public class AttrEventTriggerTest
|
|||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet();
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLowerLimit()
|
||||
throws Exception
|
||||
{
|
||||
long requestCount = 10;
|
||||
long testRangeLow = 5;
|
||||
|
||||
GreaterThanAttrEventTrigger<Long> trigger =
|
||||
|
||||
GreaterThanAttrEventTrigger<Long> trigger =
|
||||
new GreaterThanAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testRangeLow);
|
||||
|
||||
|
@ -195,27 +193,27 @@ public class AttrEventTriggerTest
|
|||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet(6,10);
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLowerLimitIncl()
|
||||
throws Exception
|
||||
{
|
||||
long requestCount = 10;
|
||||
long testRangeLow = 5;
|
||||
|
||||
GreaterThanOrEqualToAttrEventTrigger<Long> trigger =
|
||||
|
||||
GreaterThanOrEqualToAttrEventTrigger<Long> trigger =
|
||||
new GreaterThanOrEqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testRangeLow);
|
||||
|
||||
|
||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet(5,10);
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
@ -226,8 +224,8 @@ public class AttrEventTriggerTest
|
|||
{
|
||||
long requestCount = 10;
|
||||
long testRangeHigh = 5;
|
||||
|
||||
LessThanAttrEventTrigger<Long> trigger =
|
||||
|
||||
LessThanAttrEventTrigger<Long> trigger =
|
||||
new LessThanAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testRangeHigh);
|
||||
|
||||
|
@ -235,11 +233,11 @@ public class AttrEventTriggerTest
|
|||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet(1,4);
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testUpperLimitIncl()
|
||||
|
@ -247,8 +245,8 @@ public class AttrEventTriggerTest
|
|||
{
|
||||
long requestCount = 10;
|
||||
long testRangeHigh = 5;
|
||||
|
||||
LessThanOrEqualToAttrEventTrigger<Long> trigger =
|
||||
|
||||
LessThanOrEqualToAttrEventTrigger<Long> trigger =
|
||||
new LessThanOrEqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testRangeHigh);
|
||||
|
||||
|
@ -256,11 +254,11 @@ public class AttrEventTriggerTest
|
|||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet(1,5);
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRangeInclusive()
|
||||
throws Exception
|
||||
|
@ -268,20 +266,20 @@ public class AttrEventTriggerTest
|
|||
long requestCount = 10;
|
||||
long testRangeLow = 3;
|
||||
long testRangeHigh = 8;
|
||||
|
||||
RangeInclAttrEventTrigger<Long> trigger =
|
||||
|
||||
RangeInclAttrEventTrigger<Long> trigger =
|
||||
new RangeInclAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testRangeLow, testRangeHigh);
|
||||
|
||||
|
||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet(testRangeLow,testRangeHigh);
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testInsideRangeExclusive()
|
||||
throws Exception
|
||||
|
@ -289,20 +287,20 @@ public class AttrEventTriggerTest
|
|||
long requestCount = 10;
|
||||
long testRangeLow = 3;
|
||||
long testRangeHigh = 8;
|
||||
|
||||
RangeAttrEventTrigger<Long> trigger =
|
||||
|
||||
RangeAttrEventTrigger<Long> trigger =
|
||||
new RangeAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testRangeLow, testRangeHigh);
|
||||
|
||||
|
||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet(testRangeLow+1,testRangeHigh-1);
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRangeComposite()
|
||||
throws Exception
|
||||
|
@ -310,23 +308,23 @@ public class AttrEventTriggerTest
|
|||
long requestCount = 10;
|
||||
long testRangeLow = 4;
|
||||
long testRangeHigh = 7;
|
||||
|
||||
GreaterThanAttrEventTrigger<Long> trigger1 =
|
||||
|
||||
GreaterThanAttrEventTrigger<Long> trigger1 =
|
||||
new GreaterThanAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testRangeLow);
|
||||
LessThanOrEqualToAttrEventTrigger<Long> trigger2 =
|
||||
LessThanOrEqualToAttrEventTrigger<Long> trigger2 =
|
||||
new LessThanOrEqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testRangeHigh);
|
||||
AndEventTrigger trigger = new AndEventTrigger(trigger1, trigger2);
|
||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet(testRangeLow+1,testRangeHigh);
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRangeOuter()
|
||||
throws Exception
|
||||
|
@ -334,23 +332,23 @@ public class AttrEventTriggerTest
|
|||
long requestCount = 10;
|
||||
long testRangeLow = 4;
|
||||
long testRangeHigh = 7;
|
||||
|
||||
LessThanOrEqualToAttrEventTrigger<Long> trigger1 =
|
||||
|
||||
LessThanOrEqualToAttrEventTrigger<Long> trigger1 =
|
||||
new LessThanOrEqualToAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testRangeLow);
|
||||
GreaterThanAttrEventTrigger<Long> trigger2 =
|
||||
GreaterThanAttrEventTrigger<Long> trigger2 =
|
||||
new GreaterThanAttrEventTrigger<Long>("org.eclipse.jetty.monitor:type=requestcounter,id=0", "counter",
|
||||
testRangeHigh);
|
||||
OrEventTrigger trigger = new OrEventTrigger(trigger1, trigger2);
|
||||
EventNotifier notifier = new ConsoleNotifier("%s");
|
||||
CounterAction action = new CounterAction(trigger, notifier, 500, 100);
|
||||
|
||||
|
||||
performTest(action, requestCount, 1000);
|
||||
|
||||
|
||||
ResultSet result = new ResultSet(1,testRangeLow,testRangeHigh+1, requestCount);
|
||||
assertEquals(result, action.getHits());
|
||||
}
|
||||
|
||||
|
||||
protected void performTest(MonitorAction action, long count, long interval)
|
||||
throws Exception
|
||||
{
|
||||
|
@ -363,17 +361,17 @@ public class AttrEventTriggerTest
|
|||
ContentExchange getExchange = new ContentExchange();
|
||||
getExchange.setURL(_requestUrl);
|
||||
getExchange.setMethod(HttpMethods.GET);
|
||||
|
||||
|
||||
_client.send(getExchange);
|
||||
int state = getExchange.waitForDone();
|
||||
|
||||
|
||||
String content = "";
|
||||
int responseStatus = getExchange.getResponseStatus();
|
||||
if (responseStatus == HttpStatus.OK_200)
|
||||
{
|
||||
content = getExchange.getResponseContent();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
assertEquals(HttpStatus.OK_200,responseStatus);
|
||||
Thread.sleep(interval);
|
||||
}
|
||||
|
@ -382,12 +380,12 @@ public class AttrEventTriggerTest
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Thread.sleep(interval);
|
||||
|
||||
_monitor.removeActions(action);
|
||||
}
|
||||
|
||||
|
||||
protected void startClient(Realm realm)
|
||||
throws Exception
|
||||
{
|
||||
|
@ -397,7 +395,7 @@ public class AttrEventTriggerTest
|
|||
_client.setRealmResolver(new SimpleRealmResolver(realm));
|
||||
_client.start();
|
||||
}
|
||||
|
||||
|
||||
protected void stopClient()
|
||||
throws Exception
|
||||
{
|
||||
|
@ -412,7 +410,7 @@ public class AttrEventTriggerTest
|
|||
extends AbstractHandler
|
||||
{
|
||||
private RequestCounter _counter = new RequestCounter();
|
||||
|
||||
|
||||
public void handle(String target, Request baseRequest,
|
||||
HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException, ServletException
|
||||
|
@ -421,40 +419,40 @@ public class AttrEventTriggerTest
|
|||
return;
|
||||
}
|
||||
_counter.increment();
|
||||
|
||||
|
||||
response.setContentType("text/plain");
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
PrintWriter writer = response.getWriter();
|
||||
writer.println("===TEST RESPONSE===");
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
|
||||
|
||||
public RequestCounter getRequestCounter()
|
||||
{
|
||||
return _counter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static class ResultSet extends TreeSet<Long>
|
||||
{
|
||||
{
|
||||
public ResultSet() {}
|
||||
|
||||
|
||||
public ResultSet(long value)
|
||||
{
|
||||
add(value);
|
||||
}
|
||||
|
||||
|
||||
public ResultSet(long start, long end)
|
||||
{
|
||||
addEntries(start, end);
|
||||
}
|
||||
|
||||
|
||||
public ResultSet(long start, long pause, long resume, long end)
|
||||
{
|
||||
addEntries(start, pause);
|
||||
addEntries(resume, end);
|
||||
}
|
||||
|
||||
|
||||
public void addEntries(long start, long stop)
|
||||
{
|
||||
if (start > 0 && stop > 0)
|
||||
|
@ -471,23 +469,23 @@ public class AttrEventTriggerTest
|
|||
return (this.size() == set.size()) && containsAll(set);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected static class CounterAction
|
||||
extends MonitorAction
|
||||
{
|
||||
private ResultSet _hits = new ResultSet();
|
||||
|
||||
|
||||
public CounterAction(EventTrigger trigger, EventNotifier notifier, long interval, long delay)
|
||||
{
|
||||
super(trigger, notifier, interval, delay);
|
||||
}
|
||||
|
||||
|
||||
public void execute(EventTrigger trigger, EventState<?> state, long timestamp)
|
||||
{
|
||||
if (trigger != null && state != null)
|
||||
{
|
||||
Collection<?> values = state.values();
|
||||
|
||||
|
||||
Iterator<?> it = values.iterator();
|
||||
while(it.hasNext())
|
||||
{
|
||||
|
@ -500,7 +498,7 @@ public class AttrEventTriggerTest
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public ResultSet getHits()
|
||||
{
|
||||
return _hits;
|
||||
|
|
|
@ -68,7 +68,6 @@
|
|||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit4-version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -79,7 +79,7 @@ public class NoSqlSession extends AbstractSession
|
|||
__log.debug("NoSqlSession:access:active "+_active);
|
||||
if (_active.incrementAndGet()==1)
|
||||
{
|
||||
int period=_manager.getStalePeriod()*1000;
|
||||
long period=_manager.getStalePeriod()*1000L;
|
||||
if (period==0)
|
||||
refresh();
|
||||
else if (period>0)
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-osgi-boot-jsp</artifactId>
|
||||
<name>Jetty :: OSGi :: Boot JSP</name>
|
||||
<description>Jetty OSGi Boot JSP bundle</description>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-osgi-boot-warurl</artifactId>
|
||||
<name>Jetty :: OSGi :: Boot :: Warurl</name>
|
||||
<description>Jetty OSGi Boot-Warurl bundle</description>
|
||||
|
|
|
@ -14,7 +14,6 @@ Import-Package: javax.mail;version="1.4.0";resolution:=optional,
|
|||
javax.servlet.http;version="2.6",
|
||||
javax.transaction;version="1.1.0";resolution:=optional,
|
||||
javax.transaction.xa;version="1.1.0";resolution:=optional,
|
||||
org.eclipse.jetty.nested;version="8.0.0";resolution:=optional,
|
||||
org.eclipse.jetty.annotations;version="8.0.0";resolution:=optional,
|
||||
org.eclipse.jetty.deploy;version="8.0.0",
|
||||
org.eclipse.jetty.deploy.providers;version="8.0.0",
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-osgi-boot</artifactId>
|
||||
<name>Jetty :: OSGi :: Boot</name>
|
||||
<description>Jetty OSGi Boot bundle</description>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>jetty-httpservice</artifactId>
|
||||
<name>Jetty :: OSGi :: HttpService</name>
|
||||
<description>Jetty OSGi HttpService bundle</description>
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.eclipse.jetty.osgi</groupId>
|
||||
<artifactId>test-jetty-osgi</artifactId>
|
||||
<name>Jetty :: OSGi :: Test</name>
|
||||
<description>Jetty OSGi Integration test</description>
|
||||
|
@ -50,13 +49,11 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-deploy</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -68,7 +65,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlet</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -80,13 +76,11 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-jmx</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-util</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -98,7 +92,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-websocket</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!-- can't use javax.servlet:servlet-api:2.5 it is not a bundle.
|
||||
|
@ -113,13 +106,11 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.osgi</groupId>
|
||||
<artifactId>org.eclipse.osgi</artifactId>
|
||||
<version>${osgi-version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.osgi</groupId>
|
||||
<artifactId>org.eclipse.osgi.services</artifactId>
|
||||
<version>${osgi-services-version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
@ -130,7 +121,6 @@
|
|||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-servlets</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
|
@ -193,7 +183,6 @@
|
|||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>generate-resources</phase>
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
<artifactId>jetty-project</artifactId>
|
||||
<version>8.1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-policy</artifactId>
|
||||
<name>Jetty :: Policy Tool</name>
|
||||
<packaging>jar</packaging>
|
||||
|
|
|
@ -55,7 +55,7 @@ public class ProxyRule extends PatternRule
|
|||
private String _hostHeader;
|
||||
private String _proxyTo;
|
||||
|
||||
private int _connectorType = 2;
|
||||
private int _connectorType = HttpClient.CONNECTOR_SELECT_CHANNEL;
|
||||
private String _maxThreads;
|
||||
private String _maxConnections;
|
||||
private String _timeout;
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
package org.eclipse.jetty.rewrite.handler;
|
||||
|
||||
//========================================================================
|
||||
//Copyright (c) 2006-2009 Mort Bay Consulting Pty. Ltd.
|
||||
//------------------------------------------------------------------------
|
||||
|
@ -12,12 +10,10 @@ package org.eclipse.jetty.rewrite.handler;
|
|||
//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.assertEquals;
|
||||
package org.eclipse.jetty.rewrite.handler;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
@ -35,6 +31,8 @@ import org.junit.AfterClass;
|
|||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
public class ProxyRuleTest
|
||||
{
|
||||
private static ProxyRule _rule;
|
||||
|
|
|
@ -487,7 +487,7 @@ public abstract class SecurityHandler extends HandlerWrapper implements Authenti
|
|||
previousIdentity = deferred.getPreviousAssociation();
|
||||
deferred.setIdentityService(null);
|
||||
}
|
||||
|
||||
|
||||
Authentication auth=baseRequest.getAuthentication();
|
||||
if (auth instanceof Authentication.User)
|
||||
{
|
||||
|
|
|
@ -169,7 +169,7 @@ public class DeferredAuthentication implements Authentication.Deferred
|
|||
* @param response
|
||||
* @return true if this response is from a deferred call to {@link #authenticate(ServletRequest)}
|
||||
*/
|
||||
public boolean isDeferred(HttpServletResponse response)
|
||||
public static boolean isDeferred(HttpServletResponse response)
|
||||
{
|
||||
return response==__deferredResponse;
|
||||
}
|
||||
|
@ -177,7 +177,7 @@ public class DeferredAuthentication implements Authentication.Deferred
|
|||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
static HttpServletResponse __deferredResponse = new HttpServletResponse()
|
||||
final static HttpServletResponse __deferredResponse = new HttpServletResponse()
|
||||
{
|
||||
public void addCookie(Cookie cookie)
|
||||
{
|
||||
|
|
|
@ -835,11 +835,7 @@ public class ConstraintTest
|
|||
assertTrue(response.startsWith("HTTP/1.1 200 "));
|
||||
|
||||
response = _connector.getResponses("GET /ctx/forbid/post HTTP/1.0\r\n\r\n");
|
||||
System.err.println(response);
|
||||
assertTrue(response.startsWith("HTTP/1.1 200 ")); // This is so stupid, but it is the S P E C
|
||||
|
||||
|
||||
|
||||
}
|
||||
private class RequestHandler extends AbstractHandler
|
||||
{
|
||||
|
|
|
@ -115,7 +115,6 @@
|
|||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<version>1.8.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
|
|
@ -18,20 +18,21 @@ import java.net.InetAddress;
|
|||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
|
||||
import org.eclipse.jetty.http.HttpBuffers;
|
||||
import org.eclipse.jetty.http.HttpBuffersImpl;
|
||||
import org.eclipse.jetty.http.HttpFields;
|
||||
import org.eclipse.jetty.http.HttpHeaders;
|
||||
import org.eclipse.jetty.http.HttpSchemes;
|
||||
import org.eclipse.jetty.io.Buffers;
|
||||
import org.eclipse.jetty.io.Buffers.Type;
|
||||
import org.eclipse.jetty.io.Connection;
|
||||
import org.eclipse.jetty.io.EndPoint;
|
||||
import org.eclipse.jetty.io.EofException;
|
||||
import org.eclipse.jetty.util.component.AbstractLifeCycle;
|
||||
import org.eclipse.jetty.util.component.AggregateLifeCycle;
|
||||
import org.eclipse.jetty.util.component.Dumpable;
|
||||
import org.eclipse.jetty.util.component.LifeCycle;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.eclipse.jetty.util.log.Logger;
|
||||
import org.eclipse.jetty.util.statistic.CounterStatistic;
|
||||
|
@ -51,7 +52,7 @@ import org.eclipse.jetty.util.thread.ThreadPool;
|
|||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractConnector extends HttpBuffers implements Connector, Dumpable
|
||||
public abstract class AbstractConnector extends AggregateLifeCycle implements HttpBuffers, Connector, Dumpable
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(AbstractConnector.class);
|
||||
|
||||
|
@ -84,7 +85,7 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
|
|||
protected int _lowResourceMaxIdleTime = -1;
|
||||
protected int _soLingerTime = -1;
|
||||
|
||||
private transient Thread[] _acceptorThread;
|
||||
private transient Thread[] _acceptorThreads;
|
||||
|
||||
private final AtomicLong _statsStartedAt = new AtomicLong(-1L);
|
||||
|
||||
|
@ -95,11 +96,14 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
|
|||
/** duration of a connection */
|
||||
private final SampleStatistic _connectionDurationStats = new SampleStatistic();
|
||||
|
||||
protected final HttpBuffersImpl _buffers = new HttpBuffersImpl();
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public AbstractConnector()
|
||||
{
|
||||
addBean(_buffers);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -123,9 +127,16 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the ThreadPool.
|
||||
* The threadpool passed is added via {@link #addBean(Object)} so that
|
||||
* it's lifecycle may be managed as a {@link AggregateLifeCycle}.
|
||||
* @param threadPool the threadPool to set
|
||||
*/
|
||||
public void setThreadPool(ThreadPool pool)
|
||||
{
|
||||
removeBean(_threadPool);
|
||||
_threadPool = pool;
|
||||
addBean(_threadPool);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -299,20 +310,22 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
|
|||
// open listener port
|
||||
open();
|
||||
|
||||
super.doStart();
|
||||
|
||||
if (_threadPool == null)
|
||||
{
|
||||
_threadPool = _server.getThreadPool();
|
||||
if (_threadPool != _server.getThreadPool() && (_threadPool instanceof LifeCycle))
|
||||
((LifeCycle)_threadPool).start();
|
||||
addBean(_threadPool,false);
|
||||
}
|
||||
|
||||
super.doStart();
|
||||
|
||||
// Start selector thread
|
||||
synchronized (this)
|
||||
{
|
||||
_acceptorThread = new Thread[getAcceptors()];
|
||||
_acceptorThreads = new Thread[getAcceptors()];
|
||||
|
||||
for (int i = 0; i < _acceptorThread.length; i++)
|
||||
_threadPool.dispatch(new Acceptor(i));
|
||||
for (int i = 0; i < _acceptorThreads.length; i++)
|
||||
if (!_threadPool.dispatch(new Acceptor(i)))
|
||||
throw new IllegalStateException("!accepting");
|
||||
if (_threadPool.isLowOnThreads())
|
||||
LOG.warn("insufficient threads configured for {}",this);
|
||||
}
|
||||
|
@ -333,22 +346,18 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
|
|||
LOG.warn(e);
|
||||
}
|
||||
|
||||
if (_threadPool != _server.getThreadPool() && _threadPool instanceof LifeCycle)
|
||||
((LifeCycle)_threadPool).stop();
|
||||
|
||||
super.doStop();
|
||||
|
||||
Thread[] acceptors = null;
|
||||
Thread[] acceptors;
|
||||
synchronized (this)
|
||||
{
|
||||
acceptors = _acceptorThread;
|
||||
_acceptorThread = null;
|
||||
acceptors = _acceptorThreads;
|
||||
_acceptorThreads = null;
|
||||
}
|
||||
if (acceptors != null)
|
||||
{
|
||||
for (int i = 0; i < acceptors.length; i++)
|
||||
for (Thread thread : acceptors)
|
||||
{
|
||||
Thread thread = acceptors[i];
|
||||
if (thread != null)
|
||||
thread.interrupt();
|
||||
}
|
||||
|
@ -361,12 +370,12 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
|
|||
Thread[] threads;
|
||||
synchronized(this)
|
||||
{
|
||||
threads= _acceptorThread;
|
||||
threads=_acceptorThreads;
|
||||
}
|
||||
if (threads != null)
|
||||
for (int i = 0; i < threads.length; i++)
|
||||
if (threads[i] != null)
|
||||
threads[i].join();
|
||||
for (Thread thread : threads)
|
||||
if (thread != null)
|
||||
thread.join();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -786,17 +795,105 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
|
|||
_forwardedSslSessionIdHeader = forwardedSslSessionId;
|
||||
}
|
||||
|
||||
public int getRequestBufferSize()
|
||||
{
|
||||
return _buffers.getRequestBufferSize();
|
||||
}
|
||||
|
||||
public void setRequestBufferSize(int requestBufferSize)
|
||||
{
|
||||
_buffers.setRequestBufferSize(requestBufferSize);
|
||||
}
|
||||
|
||||
public int getRequestHeaderSize()
|
||||
{
|
||||
return _buffers.getRequestHeaderSize();
|
||||
}
|
||||
|
||||
public void setRequestHeaderSize(int requestHeaderSize)
|
||||
{
|
||||
_buffers.setRequestHeaderSize(requestHeaderSize);
|
||||
}
|
||||
|
||||
public int getResponseBufferSize()
|
||||
{
|
||||
return _buffers.getResponseBufferSize();
|
||||
}
|
||||
|
||||
public void setResponseBufferSize(int responseBufferSize)
|
||||
{
|
||||
_buffers.setResponseBufferSize(responseBufferSize);
|
||||
}
|
||||
|
||||
public int getResponseHeaderSize()
|
||||
{
|
||||
return _buffers.getResponseHeaderSize();
|
||||
}
|
||||
|
||||
public void setResponseHeaderSize(int responseHeaderSize)
|
||||
{
|
||||
_buffers.setResponseHeaderSize(responseHeaderSize);
|
||||
}
|
||||
|
||||
public Type getRequestBufferType()
|
||||
{
|
||||
return _buffers.getRequestBufferType();
|
||||
}
|
||||
|
||||
public Type getRequestHeaderType()
|
||||
{
|
||||
return _buffers.getRequestHeaderType();
|
||||
}
|
||||
|
||||
public Type getResponseBufferType()
|
||||
{
|
||||
return _buffers.getResponseBufferType();
|
||||
}
|
||||
|
||||
public Type getResponseHeaderType()
|
||||
{
|
||||
return _buffers.getResponseHeaderType();
|
||||
}
|
||||
|
||||
public void setRequestBuffers(Buffers requestBuffers)
|
||||
{
|
||||
_buffers.setRequestBuffers(requestBuffers);
|
||||
}
|
||||
|
||||
public void setResponseBuffers(Buffers responseBuffers)
|
||||
{
|
||||
_buffers.setResponseBuffers(responseBuffers);
|
||||
}
|
||||
|
||||
public Buffers getRequestBuffers()
|
||||
{
|
||||
return _buffers.getRequestBuffers();
|
||||
}
|
||||
|
||||
public Buffers getResponseBuffers()
|
||||
{
|
||||
return _buffers.getResponseBuffers();
|
||||
}
|
||||
|
||||
public void setMaxBuffers(int maxBuffers)
|
||||
{
|
||||
_buffers.setMaxBuffers(maxBuffers);
|
||||
}
|
||||
|
||||
public int getMaxBuffers()
|
||||
{
|
||||
return _buffers.getMaxBuffers();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
String name = this.getClass().getName();
|
||||
int dot = name.lastIndexOf('.');
|
||||
if (dot > 0)
|
||||
name = name.substring(dot + 1);
|
||||
|
||||
return name + "@" + (getHost() == null?"0.0.0.0":getHost()) + ":" + (getLocalPort() <= 0?getPort():getLocalPort()) + " "
|
||||
+ AbstractLifeCycle.getState(this);
|
||||
return String.format("%s@%s:%d %s",
|
||||
getClass().getSimpleName(),
|
||||
getHost()==null?"0.0.0.0":getHost(),
|
||||
getLocalPort()<=0?getPort():getLocalPort(),
|
||||
AbstractLifeCycle.getState(this));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -818,11 +915,11 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
|
|||
String name;
|
||||
synchronized (AbstractConnector.this)
|
||||
{
|
||||
if (_acceptorThread == null)
|
||||
if (_acceptorThreads == null)
|
||||
return;
|
||||
|
||||
_acceptorThread[_acceptor] = current;
|
||||
name = _acceptorThread[_acceptor].getName();
|
||||
_acceptorThreads[_acceptor] = current;
|
||||
name = _acceptorThreads[_acceptor].getName();
|
||||
current.setName(name + " Acceptor" + _acceptor + " " + AbstractConnector.this);
|
||||
}
|
||||
int old_priority = current.getPriority();
|
||||
|
@ -862,8 +959,8 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
|
|||
|
||||
synchronized (AbstractConnector.this)
|
||||
{
|
||||
if (_acceptorThread != null)
|
||||
_acceptorThread[_acceptor] = null;
|
||||
if (_acceptorThreads != null)
|
||||
_acceptorThreads[_acceptor] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1118,17 +1215,4 @@ public abstract class AbstractConnector extends HttpBuffers implements Connector
|
|||
oldValue = valueHolder.get();
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public String dump()
|
||||
{
|
||||
return AggregateLifeCycle.dump(this);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
out.append(String.valueOf(this)).append("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -216,9 +216,6 @@ public class AsyncContinuation implements AsyncContext, Continuation
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* (non-Javadoc)
|
||||
* @see javax.servlet.ServletRequest#isSuspended()
|
||||
*/
|
||||
public boolean isSuspending()
|
||||
{
|
||||
synchronized(this)
|
||||
|
|
|
@ -45,6 +45,7 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
_asyncEndp=(AsyncEndPoint)endpoint;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection handle() throws IOException
|
||||
{
|
||||
Connection connection = this;
|
||||
|
@ -54,10 +55,10 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
try
|
||||
{
|
||||
setCurrentConnection(this);
|
||||
|
||||
|
||||
// don't check for idle while dispatched (unless blocking IO is done).
|
||||
_asyncEndp.setCheckForIdle(false);
|
||||
|
||||
|
||||
|
||||
// While progress and the connection has not changed
|
||||
while (progress && connection==this)
|
||||
|
@ -67,7 +68,7 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
{
|
||||
// Handle resumed request
|
||||
if (_request._async.isAsync())
|
||||
{
|
||||
{
|
||||
if (_request._async.isDispatchable())
|
||||
handleRequest();
|
||||
}
|
||||
|
@ -126,10 +127,10 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
}
|
||||
else if (_request.getAsyncContinuation().isAsyncStarted())
|
||||
{
|
||||
// The request is suspended, so even though progress has been made, break the while loop
|
||||
// The request is suspended, so even though progress has been made,
|
||||
// exit the while loop by setting progress to false
|
||||
LOG.debug("suspended {}",this);
|
||||
// TODO: breaking inside finally blocks is bad: rethink how we should exit from here
|
||||
break;
|
||||
progress=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,15 +138,15 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async
|
|||
finally
|
||||
{
|
||||
setCurrentConnection(null);
|
||||
|
||||
|
||||
// If we are not suspended
|
||||
if (!_request.isAsyncStarted())
|
||||
if (!_request.getAsyncContinuation().isAsyncStarted())
|
||||
{
|
||||
// return buffers
|
||||
_parser.returnBuffers();
|
||||
_generator.returnBuffers();
|
||||
|
||||
// resuming checking for idle
|
||||
|
||||
// reenable idle checking unless request is suspended
|
||||
_asyncEndp.setCheckForIdle(true);
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,13 @@ public class BlockingHttpConnection extends AbstractHttpConnection
|
|||
_endp.shutdownOutput();
|
||||
}
|
||||
}
|
||||
|
||||
// If we don't have a committed response and we are not suspended
|
||||
if (_endp.isInputShutdown() && _generator.isIdle() && !_request.getAsyncContinuation().isSuspended())
|
||||
{
|
||||
// then no more can happen, so close.
|
||||
_endp.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -467,7 +467,6 @@ public class Response implements HttpServletResponse
|
|||
}
|
||||
}
|
||||
|
||||
location=encodeRedirectURL(location);
|
||||
resetBuffer();
|
||||
setHeader(HttpHeaders.LOCATION,location);
|
||||
setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);
|
||||
|
|
|
@ -85,7 +85,10 @@ import org.eclipse.jetty.util.resource.Resource;
|
|||
* <p>
|
||||
* If the context init parameter "org.eclipse.jetty.server.context.ManagedAttributes" is set to a comma separated list of names, then they are treated as
|
||||
* context attribute names, which if set as attributes are passed to the servers Container so that they may be managed with JMX.
|
||||
*
|
||||
* <p>
|
||||
* The maximum size of a form that can be processed by this context is controlled by the system properties org.eclipse.jetty.server.Request.maxFormKeys
|
||||
* and org.eclipse.jetty.server.Request.maxFormContentSize. These can also be configured with {@link #setMaxFormContentSize(int)} and {@link #setMaxFormKeys(int)}
|
||||
*
|
||||
* @org.apache.xbean.XBean description="Creates a basic HTTP context"
|
||||
*/
|
||||
public class ContextHandler extends ScopedHandler implements Attributes, Server.Graceful
|
||||
|
@ -130,6 +133,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
private EventListener[] _eventListeners;
|
||||
private Logger _logger;
|
||||
private boolean _allowNullPathInfo;
|
||||
private int _maxFormKeys = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormKeys",1000).intValue();
|
||||
private int _maxFormContentSize = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormContentSize",200000).intValue();
|
||||
private boolean _compactPath = false;
|
||||
private boolean _aliases = false;
|
||||
|
@ -1382,11 +1386,31 @@ public class ContextHandler extends ScopedHandler implements Attributes, Server.
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the maximum size of a form post, to protect against DOS attacks from large forms.
|
||||
* @param maxSize
|
||||
*/
|
||||
public void setMaxFormContentSize(int maxSize)
|
||||
{
|
||||
_maxFormContentSize = maxSize;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public int getMaxFormKeys()
|
||||
{
|
||||
return _maxFormKeys;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the maximum number of form Keys to protect against DOS attack from crafted hash keys.
|
||||
* @param max
|
||||
*/
|
||||
public void setMaxFormKeys(int max)
|
||||
{
|
||||
_maxFormKeys = max;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @return True if URLs are compacted to replace multiple '/'s with a single '/'
|
||||
|
|
|
@ -50,7 +50,7 @@ public class DefaultHandler extends AbstractHandler
|
|||
{
|
||||
private static final Logger LOG = Log.getLogger(DefaultHandler.class);
|
||||
|
||||
final long _faviconModified=(System.currentTimeMillis()/1000)*1000;
|
||||
final long _faviconModified=(System.currentTimeMillis()/1000)*1000L;
|
||||
byte[] _favicon;
|
||||
boolean _serveIcon=true;
|
||||
boolean _showContexts=true;
|
||||
|
|
|
@ -237,7 +237,7 @@ public class IPAccessHandler extends HandlerWrapper
|
|||
pathMap = new PathMap(true);
|
||||
patternMap.put(addr,pathMap);
|
||||
}
|
||||
if (path != null)
|
||||
if (path != null && !"".equals(path))
|
||||
pathMap.put(path,path);
|
||||
|
||||
if (deprecated)
|
||||
|
|
|
@ -4,35 +4,31 @@
|
|||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
package org.eclipse.jetty.server.nio;
|
||||
|
||||
import org.eclipse.jetty.io.Buffers.Type;
|
||||
import org.eclipse.jetty.server.AbstractConnector;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractNIOConnector extends AbstractConnector implements NIOConnector
|
||||
{
|
||||
public AbstractNIOConnector()
|
||||
{
|
||||
setRequestBufferType(Type.DIRECT);
|
||||
setRequestHeaderType(Type.INDIRECT);
|
||||
setResponseBufferType(Type.DIRECT);
|
||||
setResponseHeaderType(Type.INDIRECT);
|
||||
_buffers.setRequestBufferType(Type.DIRECT);
|
||||
_buffers.setRequestHeaderType(Type.INDIRECT);
|
||||
_buffers.setResponseBufferType(Type.DIRECT);
|
||||
_buffers.setResponseHeaderType(Type.INDIRECT);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
public boolean getUseDirectBuffers()
|
||||
{
|
||||
|
@ -46,8 +42,7 @@ public abstract class AbstractNIOConnector extends AbstractConnector implements
|
|||
*/
|
||||
public void setUseDirectBuffers(boolean direct)
|
||||
{
|
||||
setRequestBufferType(direct?Type.DIRECT:Type.INDIRECT);
|
||||
setResponseBufferType(direct?Type.DIRECT:Type.INDIRECT);
|
||||
_buffers.setRequestBufferType(direct?Type.DIRECT:Type.INDIRECT);
|
||||
_buffers.setResponseBufferType(direct?Type.DIRECT:Type.INDIRECT);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ import java.io.IOException;
|
|||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.channels.ByteChannel;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Set;
|
||||
|
@ -341,5 +342,20 @@ public class BlockingChannelConnector extends AbstractNIOConnector
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("BCEP@%x{l(%s)<->r(%s),open=%b,ishut=%b,oshut=%b}-{%s}",
|
||||
hashCode(),
|
||||
_socket.getRemoteSocketAddress(),
|
||||
_socket.getLocalSocketAddress(),
|
||||
isOpen(),
|
||||
isInputShutdown(),
|
||||
isOutputShutdown(),
|
||||
_connection);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,7 +19,6 @@ import java.net.Socket;
|
|||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.eclipse.jetty.continuation.Continuation;
|
||||
import org.eclipse.jetty.io.AsyncEndPoint;
|
||||
|
@ -32,9 +31,6 @@ import org.eclipse.jetty.io.nio.SelectorManager;
|
|||
import org.eclipse.jetty.io.nio.SelectorManager.SelectSet;
|
||||
import org.eclipse.jetty.server.AsyncHttpConnection;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
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.thread.ThreadPool;
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
|
@ -65,8 +61,6 @@ import org.eclipse.jetty.util.thread.ThreadPool;
|
|||
*/
|
||||
public class SelectChannelConnector extends AbstractNIOConnector
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(SelectChannelConnector.class);
|
||||
|
||||
protected ServerSocketChannel _acceptChannel;
|
||||
private int _lowResourcesConnections;
|
||||
private int _lowResourcesMaxIdleTime;
|
||||
|
@ -82,6 +76,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
|
|||
public SelectChannelConnector()
|
||||
{
|
||||
_manager.setMaxIdleTime(getMaxIdleTime());
|
||||
addBean(_manager,true);
|
||||
setAcceptors(Math.max(1,(Runtime.getRuntime().availableProcessors()+3)/4));
|
||||
}
|
||||
|
||||
|
@ -111,7 +106,11 @@ public class SelectChannelConnector extends AbstractNIOConnector
|
|||
synchronized(this)
|
||||
{
|
||||
if (_acceptChannel != null)
|
||||
_acceptChannel.close();
|
||||
{
|
||||
removeBean(_acceptChannel);
|
||||
if (_acceptChannel.isOpen())
|
||||
_acceptChannel.close();
|
||||
}
|
||||
_acceptChannel = null;
|
||||
_localPort=-2;
|
||||
}
|
||||
|
@ -121,7 +120,6 @@ public class SelectChannelConnector extends AbstractNIOConnector
|
|||
@Override
|
||||
public void customize(EndPoint endpoint, Request request) throws IOException
|
||||
{
|
||||
AsyncEndPoint aEndp = ((AsyncEndPoint)endpoint);
|
||||
request.setTimeStamp(System.currentTimeMillis());
|
||||
endpoint.setMaxIdleTime(_maxIdleTime);
|
||||
super.customize(endpoint, request);
|
||||
|
@ -178,6 +176,7 @@ public class SelectChannelConnector extends AbstractNIOConnector
|
|||
if (_localPort<=0)
|
||||
throw new IOException("Server channel not bound");
|
||||
|
||||
addBean(_acceptChannel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -250,31 +249,6 @@ public class SelectChannelConnector extends AbstractNIOConnector
|
|||
_manager.setLowResourcesMaxIdleTime(getLowResourcesMaxIdleTime());
|
||||
|
||||
super.doStart();
|
||||
_manager.start();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* @see org.eclipse.jetty.server.server.AbstractConnector#doStop()
|
||||
*/
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
synchronized(this)
|
||||
{
|
||||
if(_manager.isRunning())
|
||||
{
|
||||
try
|
||||
{
|
||||
_manager.stop();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOG.warn(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
super.doStop();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -297,20 +271,6 @@ public class SelectChannelConnector extends AbstractNIOConnector
|
|||
return new AsyncHttpConnection(SelectChannelConnector.this,endpoint,getServer());
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
public void dump(Appendable out, String indent) throws IOException
|
||||
{
|
||||
super.dump(out, indent);
|
||||
ServerSocketChannel channel;
|
||||
synchronized (this)
|
||||
{
|
||||
channel=_acceptChannel;
|
||||
}
|
||||
if (channel==null)
|
||||
AggregateLifeCycle.dump(out,indent,Arrays.asList(null,"CLOSED",_manager));
|
||||
else
|
||||
AggregateLifeCycle.dump(out,indent,Arrays.asList(channel,channel.isOpen()?"OPEN":"CLOSED",_manager));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -357,5 +317,4 @@ public class SelectChannelConnector extends AbstractNIOConnector
|
|||
return SelectChannelConnector.this.newEndPoint(channel,selectSet,sKey);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
|
|||
_accessed=_created;
|
||||
_lastAccessed=_created;
|
||||
_requests=1;
|
||||
_maxIdleMs=_manager._dftMaxIdleSecs>0?_manager._dftMaxIdleSecs*1000:-1;
|
||||
_maxIdleMs=_manager._dftMaxIdleSecs>0?_manager._dftMaxIdleSecs*1000L:-1;
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("new session & id "+_nodeId+" "+_clusterId);
|
||||
}
|
||||
|
@ -430,7 +430,7 @@ public abstract class AbstractSession implements AbstractSessionManager.SessionI
|
|||
/* ------------------------------------------------------------- */
|
||||
public void setMaxInactiveInterval(int secs)
|
||||
{
|
||||
_maxIdleMs=(long)secs*1000;
|
||||
_maxIdleMs=(long)secs*1000L;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------- */
|
||||
|
|
|
@ -54,9 +54,9 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
private Timer _timer;
|
||||
private boolean _timerStop=false;
|
||||
private TimerTask _task;
|
||||
int _scavengePeriodMs=30000;
|
||||
int _savePeriodMs=0; //don't do period saves by default
|
||||
int _idleSavePeriodMs = 0; // don't idle save sessions by default.
|
||||
long _scavengePeriodMs=30000;
|
||||
long _savePeriodMs=0; //don't do period saves by default
|
||||
long _idleSavePeriodMs = 0; // don't idle save sessions by default.
|
||||
private TimerTask _saveTask;
|
||||
File _storeDir;
|
||||
private boolean _lazyLoad=false;
|
||||
|
@ -135,7 +135,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
*/
|
||||
public int getScavengePeriod()
|
||||
{
|
||||
return _scavengePeriodMs/1000;
|
||||
return (int)(_scavengePeriodMs/1000);
|
||||
}
|
||||
|
||||
|
||||
|
@ -161,7 +161,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
if (_idleSavePeriodMs <= 0)
|
||||
return 0;
|
||||
|
||||
return _idleSavePeriodMs / 1000;
|
||||
return (int)(_idleSavePeriodMs / 1000);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -175,7 +175,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
*/
|
||||
public void setIdleSavePeriod(int seconds)
|
||||
{
|
||||
_idleSavePeriodMs = seconds * 1000;
|
||||
_idleSavePeriodMs = seconds * 1000L;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -183,7 +183,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
public void setMaxInactiveInterval(int seconds)
|
||||
{
|
||||
super.setMaxInactiveInterval(seconds);
|
||||
if (_dftMaxIdleSecs>0&&_scavengePeriodMs>_dftMaxIdleSecs*1000)
|
||||
if (_dftMaxIdleSecs>0&&_scavengePeriodMs>_dftMaxIdleSecs*1000L)
|
||||
setScavengePeriod((_dftMaxIdleSecs+9)/10);
|
||||
}
|
||||
|
||||
|
@ -193,7 +193,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
*/
|
||||
public void setSavePeriod (int seconds)
|
||||
{
|
||||
int period = (seconds * 1000);
|
||||
long period = (seconds * 1000L);
|
||||
if (period < 0)
|
||||
period=0;
|
||||
_savePeriodMs=period;
|
||||
|
@ -236,7 +236,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
if (_savePeriodMs<=0)
|
||||
return 0;
|
||||
|
||||
return _savePeriodMs/1000;
|
||||
return (int)(_savePeriodMs/1000);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -248,8 +248,8 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
if (seconds==0)
|
||||
seconds=60;
|
||||
|
||||
int old_period=_scavengePeriodMs;
|
||||
int period=seconds*1000;
|
||||
long old_period=_scavengePeriodMs;
|
||||
long period=seconds*1000L;
|
||||
if (period>60000)
|
||||
period=60000;
|
||||
if (period<1000)
|
||||
|
@ -298,7 +298,7 @@ public class HashSessionManager extends AbstractSessionManager
|
|||
for (Iterator<HashedSession> i=_sessions.values().iterator(); i.hasNext();)
|
||||
{
|
||||
HashedSession session=i.next();
|
||||
long idleTime=session.getMaxInactiveInterval()*1000;
|
||||
long idleTime=session.getMaxInactiveInterval()*1000L;
|
||||
if (idleTime>0&&session.getAccessed()+idleTime<now)
|
||||
{
|
||||
// Found a stale session, add it to the list
|
||||
|
|
|
@ -60,7 +60,7 @@ public class HashedSession extends AbstractSession
|
|||
public void setMaxInactiveInterval(int secs)
|
||||
{
|
||||
super.setMaxInactiveInterval(secs);
|
||||
if (getMaxInactiveInterval()>0&&(getMaxInactiveInterval()*1000/10)<_hashSessionManager._scavengePeriodMs)
|
||||
if (getMaxInactiveInterval()>0&&(getMaxInactiveInterval()*1000L/10)<_hashSessionManager._scavengePeriodMs)
|
||||
_hashSessionManager.setScavengePeriod((secs+9)/10);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
protected Timer _timer; //scavenge timer
|
||||
protected TimerTask _task; //scavenge task
|
||||
protected long _lastScavengeTime;
|
||||
protected long _scavengeIntervalMs = 1000 * 60 * 10; //10mins
|
||||
protected long _scavengeIntervalMs = 1000L * 60 * 10; //10mins
|
||||
protected String _blobType; //if not set, is deduced from the type of the database at runtime
|
||||
|
||||
protected String _createSessionIdTable;
|
||||
|
@ -245,7 +245,7 @@ public class JDBCSessionIdManager extends AbstractSessionIdManager
|
|||
sec=60;
|
||||
|
||||
long old_period=_scavengeIntervalMs;
|
||||
long period=sec*1000;
|
||||
long period=sec*1000L;
|
||||
|
||||
_scavengeIntervalMs=period;
|
||||
|
||||
|
|
|
@ -279,11 +279,11 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
super(JDBCSessionManager.this,request);
|
||||
_data = new SessionData(getClusterId(),_jdbcAttributes);
|
||||
if (_dftMaxIdleSecs>0)
|
||||
_data.setMaxIdleMs(_dftMaxIdleSecs*1000);
|
||||
_data.setMaxIdleMs(_dftMaxIdleSecs*1000L);
|
||||
_data.setCanonicalContext(canonicalize(_context.getContextPath()));
|
||||
_data.setVirtualHost(getVirtualHost(_context));
|
||||
int maxInterval=getMaxInactiveInterval();
|
||||
_data.setExpiryTime(maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000));
|
||||
_data.setExpiryTime(maxInterval <= 0 ? 0 : (System.currentTimeMillis() + maxInterval*1000L));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -295,7 +295,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
super(JDBCSessionManager.this,data.getCreated(), accessed, data.getId());
|
||||
_data=data;
|
||||
if (_dftMaxIdleSecs>0)
|
||||
_data.setMaxIdleMs(_dftMaxIdleSecs*1000);
|
||||
_data.setMaxIdleMs(_dftMaxIdleSecs*1000L);
|
||||
_jdbcAttributes.putAll(_data.getAttributeMap());
|
||||
_data.setAttributeMap(_jdbcAttributes);
|
||||
}
|
||||
|
@ -335,7 +335,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
_data.setAccessed(time);
|
||||
|
||||
int maxInterval=getMaxInactiveInterval();
|
||||
_data.setExpiryTime(maxInterval <= 0 ? 0 : (time + maxInterval*1000));
|
||||
_data.setExpiryTime(maxInterval <= 0 ? 0 : (time + maxInterval*1000L));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -359,7 +359,7 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
updateSession(_data);
|
||||
didActivate();
|
||||
}
|
||||
else if ((_data._accessed - _data._lastSaved) >= (getSaveInterval() * 1000))
|
||||
else if ((_data._accessed - _data._lastSaved) >= (getSaveInterval() * 1000L))
|
||||
{
|
||||
updateSessionAccessTime(_data);
|
||||
}
|
||||
|
@ -508,23 +508,23 @@ public class JDBCSessionManager extends AbstractSessionManager
|
|||
LOG.debug("getSession("+idInCluster+"): not in session map,"+
|
||||
" now="+now+
|
||||
" lastSaved="+(session==null?0:session._data._lastSaved)+
|
||||
" interval="+(_saveIntervalSec * 1000));
|
||||
" interval="+(_saveIntervalSec * 1000L));
|
||||
else
|
||||
LOG.debug("getSession("+idInCluster+"): in session map, "+
|
||||
" now="+now+
|
||||
" lastSaved="+(session==null?0:session._data._lastSaved)+
|
||||
" interval="+(_saveIntervalSec * 1000)+
|
||||
" interval="+(_saveIntervalSec * 1000L)+
|
||||
" lastNode="+session._data.getLastNode()+
|
||||
" thisNode="+getSessionIdManager().getWorkerName()+
|
||||
" difference="+(now - session._data._lastSaved));
|
||||
}
|
||||
|
||||
if (session==null || ((now - session._data._lastSaved) >= (_saveIntervalSec * 1000)))
|
||||
if (session==null || ((now - session._data._lastSaved) >= (_saveIntervalSec * 1000L)))
|
||||
{
|
||||
LOG.debug("getSession("+idInCluster+"): no session in session map or stale session. Reloading session data from db.");
|
||||
data = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context));
|
||||
}
|
||||
else if ((now - session._data._lastSaved) >= (_saveIntervalSec * 1000))
|
||||
else if ((now - session._data._lastSaved) >= (_saveIntervalSec * 1000L))
|
||||
{
|
||||
LOG.debug("getSession("+idInCluster+"): stale session. Reloading session data from db.");
|
||||
data = loadSession(idInCluster, canonicalize(_context.getContextPath()), getVirtualHost(_context));
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.eclipse.jetty.io.nio.AsyncConnection;
|
|||
import org.eclipse.jetty.io.nio.SslConnection;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.util.component.AggregateLifeCycle;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -54,9 +55,15 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
|
|||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** 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);
|
||||
setUseDirectBuffers(false);
|
||||
setSoLingerTime(30000);
|
||||
}
|
||||
|
@ -597,7 +604,6 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
|
|||
protected void doStart() throws Exception
|
||||
{
|
||||
_sslContextFactory.checkKeyStore();
|
||||
|
||||
_sslContextFactory.start();
|
||||
|
||||
SSLEngine sslEngine = _sslContextFactory.newSslEngine();
|
||||
|
@ -627,7 +633,6 @@ public class SslSelectChannelConnector extends SelectChannelConnector implements
|
|||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
_sslContextFactory.stop();
|
||||
_sslBuffers=null;
|
||||
super.doStop();
|
||||
}
|
||||
|
|
|
@ -39,6 +39,9 @@ import static org.junit.matchers.JUnitMatchers.containsString;
|
|||
public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
||||
{
|
||||
protected static final int MAX_IDLE_TIME=250;
|
||||
private int sleepTime = MAX_IDLE_TIME + MAX_IDLE_TIME/5;
|
||||
private int minimumTestRuntime = MAX_IDLE_TIME-MAX_IDLE_TIME/5;
|
||||
private int maximumTestRuntime = MAX_IDLE_TIME*10;
|
||||
|
||||
static
|
||||
{
|
||||
|
@ -68,11 +71,11 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
long start = System.currentTimeMillis();
|
||||
IO.toString(is);
|
||||
|
||||
Thread.sleep(300);
|
||||
Thread.sleep(sleepTime);
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
Assert.assertTrue(System.currentTimeMillis()-start>200);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<5000);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start>minimumTestRuntime);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<maximumTestRuntime);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -101,11 +104,11 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
long start = System.currentTimeMillis();
|
||||
IO.toString(is);
|
||||
|
||||
Thread.sleep(300);
|
||||
Thread.sleep(sleepTime);
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
Assert.assertTrue(System.currentTimeMillis()-start>200);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<5000);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start>minimumTestRuntime);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<maximumTestRuntime);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -126,7 +129,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
{}
|
||||
super.handle(target,baseRequest,request,response);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
@ -151,14 +154,14 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
// read the response
|
||||
String result=IO.toString(is);
|
||||
Assert.assertThat("OK",result,containsString("200 OK"));
|
||||
|
||||
|
||||
// check client reads EOF
|
||||
assertEquals(-1, is.read());
|
||||
|
||||
// wait for idle timeout
|
||||
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+MAX_IDLE_TIME/2);
|
||||
|
||||
|
||||
|
||||
// further writes will get broken pipe or similar
|
||||
try
|
||||
{
|
||||
|
@ -199,7 +202,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
{}
|
||||
super.handle(target,baseRequest,request,response);
|
||||
}
|
||||
|
||||
|
||||
});
|
||||
Socket client=newSocket(HOST,_connector.getLocalPort());
|
||||
client.setSoTimeout(10000);
|
||||
|
@ -220,10 +223,10 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
"\r\n").getBytes("utf-8"));
|
||||
os.write(contentB);
|
||||
os.flush();
|
||||
|
||||
|
||||
// Get the server side endpoint
|
||||
EndPoint endp = endpoint.exchange(null,10,TimeUnit.SECONDS);
|
||||
|
||||
|
||||
// read the response
|
||||
IO.toString(is);
|
||||
|
||||
|
@ -232,7 +235,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
|
||||
TimeUnit.MILLISECONDS.sleep(MAX_IDLE_TIME+MAX_IDLE_TIME/2);
|
||||
|
||||
|
||||
|
||||
// further writes will get broken pipe or similar
|
||||
try
|
||||
{
|
||||
|
@ -251,7 +254,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
{
|
||||
// expected
|
||||
}
|
||||
|
||||
|
||||
// check the server side is closed
|
||||
Assert.assertFalse(endp.isOpen());
|
||||
}
|
||||
|
@ -266,7 +269,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
InputStream is=client.getInputStream();
|
||||
assertFalse(client.isClosed());
|
||||
|
||||
Thread.sleep(500);
|
||||
Thread.sleep(sleepTime);
|
||||
long start = System.currentTimeMillis();
|
||||
try
|
||||
{
|
||||
|
@ -281,7 +284,7 @@ public abstract class ConnectorTimeoutTest extends HttpServerTestFixture
|
|||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<5000);
|
||||
Assert.assertTrue(System.currentTimeMillis()-start<maximumTestRuntime);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -200,288 +200,12 @@ public class LocalAsyncContextTest
|
|||
return ((LocalConnector)_connector).getResponses(request);
|
||||
}
|
||||
|
||||
private static class SuspendHandler extends HandlerWrapper
|
||||
{
|
||||
private int _read;
|
||||
private long _suspendFor=-1;
|
||||
private long _resumeAfter=-1;
|
||||
private long _completeAfter=-1;
|
||||
private long _suspendFor2=-1;
|
||||
private long _resumeAfter2=-1;
|
||||
private long _completeAfter2=-1;
|
||||
|
||||
public SuspendHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public int getRead()
|
||||
{
|
||||
return _read;
|
||||
}
|
||||
|
||||
public void setRead(int read)
|
||||
{
|
||||
_read = read;
|
||||
}
|
||||
|
||||
public long getSuspendFor()
|
||||
{
|
||||
return _suspendFor;
|
||||
}
|
||||
|
||||
public void setSuspendFor(long suspendFor)
|
||||
{
|
||||
_suspendFor = suspendFor;
|
||||
}
|
||||
|
||||
public long getResumeAfter()
|
||||
{
|
||||
return _resumeAfter;
|
||||
}
|
||||
|
||||
public void setResumeAfter(long resumeAfter)
|
||||
{
|
||||
_resumeAfter = resumeAfter;
|
||||
}
|
||||
|
||||
public long getCompleteAfter()
|
||||
{
|
||||
return _completeAfter;
|
||||
}
|
||||
|
||||
public void setCompleteAfter(long completeAfter)
|
||||
{
|
||||
_completeAfter = completeAfter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the suspendFor2.
|
||||
* @return the suspendFor2
|
||||
*/
|
||||
public long getSuspendFor2()
|
||||
{
|
||||
return _suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the suspendFor2.
|
||||
* @param suspendFor2 the suspendFor2 to set
|
||||
*/
|
||||
public void setSuspendFor2(long suspendFor2)
|
||||
{
|
||||
_suspendFor2 = suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the resumeAfter2.
|
||||
* @return the resumeAfter2
|
||||
*/
|
||||
public long getResumeAfter2()
|
||||
{
|
||||
return _resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the resumeAfter2.
|
||||
* @param resumeAfter2 the resumeAfter2 to set
|
||||
*/
|
||||
public void setResumeAfter2(long resumeAfter2)
|
||||
{
|
||||
_resumeAfter2 = resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the completeAfter2.
|
||||
* @return the completeAfter2
|
||||
*/
|
||||
public long getCompleteAfter2()
|
||||
{
|
||||
return _completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the completeAfter2.
|
||||
* @param completeAfter2 the completeAfter2 to set
|
||||
*/
|
||||
public void setCompleteAfter2(long completeAfter2)
|
||||
{
|
||||
_completeAfter2 = completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
|
||||
{
|
||||
if (_read>0)
|
||||
{
|
||||
byte[] buf=new byte[_read];
|
||||
request.getInputStream().read(buf);
|
||||
}
|
||||
else if (_read<0)
|
||||
{
|
||||
InputStream in = request.getInputStream();
|
||||
int b=in.read();
|
||||
while(b!=-1)
|
||||
b=in.read();
|
||||
}
|
||||
|
||||
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC");
|
||||
asyncContext.addListener(__asyncListener);
|
||||
asyncContext.addListener(__asyncListener1);
|
||||
if (_suspendFor>0)
|
||||
asyncContext.setTimeout(_suspendFor);
|
||||
|
||||
|
||||
if (_completeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter);
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter);
|
||||
if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null)
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request.getAttribute("TIMEOUT")!=null)
|
||||
response.getOutputStream().println("TIMEOUT");
|
||||
else
|
||||
response.getOutputStream().println("DISPATCHED");
|
||||
|
||||
if (_suspendFor2>=0)
|
||||
{
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC2");
|
||||
if (_suspendFor2>0)
|
||||
asyncContext.setTimeout(_suspendFor2);
|
||||
_suspendFor2=-1;
|
||||
|
||||
if (_completeAfter2>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter2);
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter2==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter2>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter2);
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter2==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static AtomicInteger __completed = new AtomicInteger();
|
||||
static AtomicInteger __completed1 = new AtomicInteger();
|
||||
|
||||
private static AsyncListener __asyncListener = new AsyncListener()
|
||||
static AsyncListener __asyncListener = new AsyncListener()
|
||||
{
|
||||
|
||||
@Override
|
||||
|
@ -512,7 +236,7 @@ public class LocalAsyncContextTest
|
|||
|
||||
};
|
||||
|
||||
private static AsyncListener __asyncListener1 = new AsyncListener()
|
||||
static AsyncListener __asyncListener1 = new AsyncListener()
|
||||
{
|
||||
|
||||
@Override
|
||||
|
|
|
@ -19,12 +19,16 @@ import static org.junit.Assert.assertNotSame;
|
|||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
|
@ -34,9 +38,12 @@ import javax.servlet.http.HttpServletResponse;
|
|||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.server.handler.AbstractHandler;
|
||||
import org.eclipse.jetty.server.handler.ContextHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.StringUtil;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -72,7 +79,7 @@ public class RequestTest
|
|||
_server.stop();
|
||||
_server.join();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testParamExtraction() throws Exception
|
||||
{
|
||||
|
@ -95,27 +102,27 @@ public class RequestTest
|
|||
System.err.println(map);
|
||||
assertFalse(map == null);
|
||||
assertTrue(map.isEmpty());
|
||||
|
||||
|
||||
Enumeration names = request.getParameterNames();
|
||||
assertFalse(names.hasMoreElements());
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//Send a request with query string with illegal hex code to cause
|
||||
//an exception parsing the params
|
||||
String request="GET /?param=%ZZaaa HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Content-Type: text/html;charset=utf8\n"+
|
||||
"\n";
|
||||
|
||||
|
||||
String responses=_connector.getResponses(request);
|
||||
assertTrue(responses.startsWith("HTTP/1.1 200"));
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBadUtf8ParamExtraction() throws Exception
|
||||
{
|
||||
|
@ -127,20 +134,40 @@ public class RequestTest
|
|||
return value.startsWith("aaa") && value.endsWith("bb");
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//Send a request with query string with illegal hex code to cause
|
||||
//an exception parsing the params
|
||||
String request="GET /?param=aaa%E7bbb HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Content-Type: text/html;charset=utf8\n"+
|
||||
"\n";
|
||||
|
||||
|
||||
String responses=_connector.getResponses(request);
|
||||
assertTrue(responses.startsWith("HTTP/1.1 200"));
|
||||
assertTrue(responses.startsWith("HTTP/1.1 200"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testInvalidHostHeader() throws Exception
|
||||
{
|
||||
// Use a contextHandler with vhosts to force call to Request.getServerName()
|
||||
ContextHandler handler = new ContextHandler();
|
||||
handler.addVirtualHosts(new String[1]);
|
||||
_server.stop();
|
||||
_server.setHandler(handler);
|
||||
_server.start();
|
||||
|
||||
// Request with illegal Host header
|
||||
String request="GET / HTTP/1.1\r\n"+
|
||||
"Host: whatever.com:\r\n"+
|
||||
"Content-Type: text/html;charset=utf8\n"+
|
||||
"\n";
|
||||
|
||||
String responses=_connector.getResponses(request);
|
||||
assertTrue("400 Bad Request response expected",responses.startsWith("HTTP/1.1 400"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testContentTypeEncoding() throws Exception
|
||||
{
|
||||
|
@ -190,7 +217,7 @@ public class RequestTest
|
|||
assertTrue(results.get(i++).startsWith("text/html"));
|
||||
assertEquals(" x=z; ",results.get(i++));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHostPort() throws Exception
|
||||
{
|
||||
|
@ -363,7 +390,7 @@ public class RequestTest
|
|||
Reader reader=request.getReader();
|
||||
String in = IO.toString(reader);
|
||||
String param = request.getParameter("param");
|
||||
|
||||
|
||||
byte[] b=("read='"+in+"' param="+param+"\n").getBytes(StringUtil.__UTF8);
|
||||
response.setContentLength(b.length);
|
||||
response.getOutputStream().write(b);
|
||||
|
@ -383,11 +410,11 @@ public class RequestTest
|
|||
"param=wrong\r\n";
|
||||
|
||||
String responses = _connector.getResponses(request);
|
||||
|
||||
|
||||
assertTrue(responses.indexOf("read='param=wrong' param=right")>0);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testPartialInput() throws Exception
|
||||
{
|
||||
|
@ -742,6 +769,56 @@ public class RequestTest
|
|||
assertEquals(null,cookie[1]);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testHashDOS() throws Exception
|
||||
{
|
||||
_server.setAttribute("org.eclipse.jetty.server.Request.maxFormContentSize",-1);
|
||||
_server.setAttribute("org.eclipse.jetty.server.Request.maxFormKeys",1000);
|
||||
|
||||
// This file is not distributed - as it is dangerous
|
||||
File evil_keys = new File("/tmp/keys_mapping_to_zero_2m");
|
||||
if (!evil_keys.exists())
|
||||
{
|
||||
Log.info("testHashDOS skipped");
|
||||
return;
|
||||
}
|
||||
|
||||
BufferedReader in = new BufferedReader(new FileReader(evil_keys));
|
||||
StringBuilder buf = new StringBuilder(4000000);
|
||||
|
||||
String key=null;
|
||||
buf.append("a=b");
|
||||
while((key=in.readLine())!=null)
|
||||
{
|
||||
buf.append("&").append(key).append("=").append("x");
|
||||
}
|
||||
buf.append("&c=d");
|
||||
|
||||
_handler._checker = new RequestTester()
|
||||
{
|
||||
public boolean check(HttpServletRequest request,HttpServletResponse response)
|
||||
{
|
||||
return "b".equals(request.getParameter("a")) && request.getParameter("c")==null;
|
||||
}
|
||||
};
|
||||
|
||||
String request="POST / HTTP/1.1\r\n"+
|
||||
"Host: whatever\r\n"+
|
||||
"Content-Type: "+MimeTypes.FORM_ENCODED+"\r\n"+
|
||||
"Content-Length: "+buf.length()+"\r\n"+
|
||||
"Connection: close\r\n"+
|
||||
"\r\n"+
|
||||
buf;
|
||||
|
||||
long start=System.currentTimeMillis();
|
||||
String response = _connector.getResponses(request);
|
||||
assertTrue(response.contains("200 OK"));
|
||||
long now=System.currentTimeMillis();
|
||||
assertTrue((now-start)<5000);
|
||||
}
|
||||
|
||||
|
||||
interface RequestTester
|
||||
{
|
||||
boolean check(HttpServletRequest request,HttpServletResponse response) throws IOException;
|
||||
|
@ -756,13 +833,15 @@ public class RequestTest
|
|||
{
|
||||
((Request)request).setHandled(true);
|
||||
|
||||
if (request.getContentLength()>0)
|
||||
if (request.getContentLength()>0 && !MimeTypes.FORM_ENCODED.equals(request.getContentType()))
|
||||
_content=IO.toString(request.getInputStream());
|
||||
|
||||
if (_checker!=null && _checker.check(request,response))
|
||||
response.setStatus(200);
|
||||
else
|
||||
response.sendError(500);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,17 +13,97 @@
|
|||
|
||||
package org.eclipse.jetty.server;
|
||||
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.eclipse.jetty.server.nio.SelectChannelConnector;
|
||||
import org.eclipse.jetty.server.session.SessionHandler;
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class SelectChannelTimeoutTest extends ConnectorTimeoutTest
|
||||
{
|
||||
|
||||
@BeforeClass
|
||||
public static void init() throws Exception
|
||||
{
|
||||
SelectChannelConnector connector = new SelectChannelConnector();
|
||||
connector.setMaxIdleTime(MAX_IDLE_TIME); //250 msec max idle
|
||||
connector.setMaxIdleTime(MAX_IDLE_TIME); // 250 msec max idle
|
||||
startServer(connector);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleTimeoutAfterSuspend() throws Exception
|
||||
{
|
||||
SuspendHandler _handler = new SuspendHandler();
|
||||
_server.stop();
|
||||
SessionHandler session = new SessionHandler();
|
||||
session.setHandler(_handler);
|
||||
_server.setHandler(session);
|
||||
_server.start();
|
||||
|
||||
_handler.setSuspendFor(100);
|
||||
_handler.setResumeAfter(25);
|
||||
assertTrue(process(null).toUpperCase().contains("DISPATCHED"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleTimeoutAfterTimeout() throws Exception
|
||||
{
|
||||
SuspendHandler _handler = new SuspendHandler();
|
||||
_server.stop();
|
||||
SessionHandler session = new SessionHandler();
|
||||
session.setHandler(_handler);
|
||||
_server.setHandler(session);
|
||||
_server.start();
|
||||
|
||||
_handler.setSuspendFor(50);
|
||||
assertTrue(process(null).toUpperCase().contains("TIMEOUT"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIdleTimeoutAfterComplete() throws Exception
|
||||
{
|
||||
SuspendHandler _handler = new SuspendHandler();
|
||||
_server.stop();
|
||||
SessionHandler session = new SessionHandler();
|
||||
session.setHandler(_handler);
|
||||
_server.setHandler(session);
|
||||
_server.start();
|
||||
|
||||
_handler.setSuspendFor(100);
|
||||
_handler.setCompleteAfter(25);
|
||||
assertTrue(process(null).toUpperCase().contains("COMPLETED"));
|
||||
}
|
||||
|
||||
private synchronized String process(String content) throws UnsupportedEncodingException, IOException, InterruptedException
|
||||
{
|
||||
String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n";
|
||||
|
||||
if (content == null)
|
||||
request += "\r\n";
|
||||
else
|
||||
request += "Content-Length: " + content.length() + "\r\n" + "\r\n" + content;
|
||||
return getResponse(request);
|
||||
}
|
||||
|
||||
private String getResponse(String request) throws UnsupportedEncodingException, IOException, InterruptedException
|
||||
{
|
||||
SelectChannelConnector connector = (SelectChannelConnector)_connector;
|
||||
Socket socket = new Socket((String)null,connector.getLocalPort());
|
||||
socket.setSoTimeout(10 * MAX_IDLE_TIME);
|
||||
socket.getOutputStream().write(request.getBytes("UTF-8"));
|
||||
InputStream inputStream = socket.getInputStream();
|
||||
long start = System.currentTimeMillis();
|
||||
String response = IO.toString(inputStream);
|
||||
long timeElapsed = System.currentTimeMillis() - start;
|
||||
assertTrue("Time elapsed should be at least MAX_IDLE_TIME",timeElapsed > MAX_IDLE_TIME);
|
||||
return response;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,290 @@
|
|||
package org.eclipse.jetty.server;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import javax.servlet.AsyncContext;
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.eclipse.jetty.server.handler.HandlerWrapper;
|
||||
|
||||
class SuspendHandler extends HandlerWrapper
|
||||
{
|
||||
private int _read;
|
||||
private long _suspendFor=-1;
|
||||
private long _resumeAfter=-1;
|
||||
private long _completeAfter=-1;
|
||||
private long _suspendFor2=-1;
|
||||
private long _resumeAfter2=-1;
|
||||
private long _completeAfter2=-1;
|
||||
|
||||
public SuspendHandler()
|
||||
{
|
||||
}
|
||||
|
||||
public int getRead()
|
||||
{
|
||||
return _read;
|
||||
}
|
||||
|
||||
public void setRead(int read)
|
||||
{
|
||||
_read = read;
|
||||
}
|
||||
|
||||
public long getSuspendFor()
|
||||
{
|
||||
return _suspendFor;
|
||||
}
|
||||
|
||||
public void setSuspendFor(long suspendFor)
|
||||
{
|
||||
_suspendFor = suspendFor;
|
||||
}
|
||||
|
||||
public long getResumeAfter()
|
||||
{
|
||||
return _resumeAfter;
|
||||
}
|
||||
|
||||
public void setResumeAfter(long resumeAfter)
|
||||
{
|
||||
_resumeAfter = resumeAfter;
|
||||
}
|
||||
|
||||
public long getCompleteAfter()
|
||||
{
|
||||
return _completeAfter;
|
||||
}
|
||||
|
||||
public void setCompleteAfter(long completeAfter)
|
||||
{
|
||||
_completeAfter = completeAfter;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the suspendFor2.
|
||||
* @return the suspendFor2
|
||||
*/
|
||||
public long getSuspendFor2()
|
||||
{
|
||||
return _suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the suspendFor2.
|
||||
* @param suspendFor2 the suspendFor2 to set
|
||||
*/
|
||||
public void setSuspendFor2(long suspendFor2)
|
||||
{
|
||||
_suspendFor2 = suspendFor2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the resumeAfter2.
|
||||
* @return the resumeAfter2
|
||||
*/
|
||||
public long getResumeAfter2()
|
||||
{
|
||||
return _resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the resumeAfter2.
|
||||
* @param resumeAfter2 the resumeAfter2 to set
|
||||
*/
|
||||
public void setResumeAfter2(long resumeAfter2)
|
||||
{
|
||||
_resumeAfter2 = resumeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get the completeAfter2.
|
||||
* @return the completeAfter2
|
||||
*/
|
||||
public long getCompleteAfter2()
|
||||
{
|
||||
return _completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Set the completeAfter2.
|
||||
* @param completeAfter2 the completeAfter2 to set
|
||||
*/
|
||||
public void setCompleteAfter2(long completeAfter2)
|
||||
{
|
||||
_completeAfter2 = completeAfter2;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void handle(String target, final Request baseRequest, final HttpServletRequest request, final HttpServletResponse response) throws IOException, ServletException
|
||||
{
|
||||
try
|
||||
{
|
||||
if (DispatcherType.REQUEST.equals(baseRequest.getDispatcherType()))
|
||||
{
|
||||
if (_read>0)
|
||||
{
|
||||
byte[] buf=new byte[_read];
|
||||
request.getInputStream().read(buf);
|
||||
}
|
||||
else if (_read<0)
|
||||
{
|
||||
InputStream in = request.getInputStream();
|
||||
int b=in.read();
|
||||
while(b!=-1)
|
||||
b=in.read();
|
||||
}
|
||||
|
||||
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC");
|
||||
asyncContext.addListener(LocalAsyncContextTest.__asyncListener);
|
||||
asyncContext.addListener(LocalAsyncContextTest.__asyncListener1);
|
||||
if (_suspendFor>0)
|
||||
asyncContext.setTimeout(_suspendFor);
|
||||
|
||||
|
||||
if (_completeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter);
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter);
|
||||
if(((HttpServletRequest)asyncContext.getRequest()).getSession(true).getId()!=null)
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request.getAttribute("TIMEOUT")!=null)
|
||||
response.getOutputStream().println("TIMEOUT");
|
||||
else
|
||||
response.getOutputStream().println("DISPATCHED");
|
||||
|
||||
if (_suspendFor2>=0)
|
||||
{
|
||||
final AsyncContext asyncContext = baseRequest.startAsync();
|
||||
response.getOutputStream().println("STARTASYNC2");
|
||||
if (_suspendFor2>0)
|
||||
asyncContext.setTimeout(_suspendFor2);
|
||||
_suspendFor2=-1;
|
||||
|
||||
if (_completeAfter2>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_completeAfter2);
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_completeAfter2==0)
|
||||
{
|
||||
response.getOutputStream().println("COMPLETED2");
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
asyncContext.complete();
|
||||
}
|
||||
|
||||
if (_resumeAfter2>0)
|
||||
{
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.sleep(_resumeAfter2);
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
else if (_resumeAfter2==0)
|
||||
{
|
||||
asyncContext.dispatch();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
response.setStatus(200);
|
||||
baseRequest.setHandled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -374,8 +374,8 @@ public class ServletHandler extends ScopedHandler
|
|||
|
||||
String servlet_path_spec=(String)entry.getKey();
|
||||
String servlet_path=entry.getMapped()!=null?entry.getMapped():PathMap.pathMatch(servlet_path_spec,target);
|
||||
String path_info=PathMap.pathInfo(servlet_path_spec,target);
|
||||
|
||||
String path_info=PathMap.pathInfo(servlet_path_spec,target);
|
||||
|
||||
if (DispatcherType.INCLUDE.equals(type))
|
||||
{
|
||||
baseRequest.setAttribute(Dispatcher.INCLUDE_SERVLET_PATH,servlet_path);
|
||||
|
@ -393,7 +393,7 @@ public class ServletHandler extends ScopedHandler
|
|||
// look for a servlet by name!
|
||||
servlet_holder=(ServletHolder)_servletNameMap.get(target);
|
||||
}
|
||||
|
||||
|
||||
if (LOG.isDebugEnabled())
|
||||
LOG.debug("servlet {}|{}|{} -> {}",baseRequest.getContextPath(),baseRequest.getServletPath(),baseRequest.getPathInfo(),servlet_holder);
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class ELContextCleaner implements ServletContextListener
|
|||
}
|
||||
catch (NoSuchFieldException e)
|
||||
{
|
||||
LOG.warn("Cannot purge classes from javax.el.BeanELResolver", e);
|
||||
LOG.info("Not cleaning cached beans: no such field javax.el.BeanELResolver.properties");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -3,4 +3,3 @@ name: RO:Name
|
|||
displayName: RO:Display Name
|
||||
className: RO:Class Name
|
||||
initParameters: RO:Initial parameters
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.FilterConfig;
|
||||
|
@ -42,7 +43,14 @@ import org.eclipse.jetty.util.log.Logger;
|
|||
* <ul>
|
||||
* <li><b>allowedOrigins</b>, a comma separated list of origins that are
|
||||
* allowed to access the resources. Default value is <b>*</b>, meaning all
|
||||
* origins</li>
|
||||
* origins.<br />
|
||||
* If an allowed origin contains one or more * characters (for example
|
||||
* http://*.domain.com), then "*" characters are converted to ".*", "."
|
||||
* characters are escaped to "\." and the resulting allowed origin
|
||||
* interpreted as a regular expression.<br />
|
||||
* Allowed origins can therefore be more complex expressions such as
|
||||
* https?://*.domain.[a-z]{3} that matches http or https, multiple subdomains
|
||||
* and any 3 letter top-level domain (.com, .net, .org, etc.).</li>
|
||||
* <li><b>allowedMethods</b>, a comma separated list of HTTP methods that
|
||||
* are allowed to be used when accessing the resources. Default value is
|
||||
* <b>GET,POST</b></li>
|
||||
|
@ -229,19 +237,34 @@ public class CrossOriginFilter implements Filter
|
|||
if (origin.trim().length() == 0)
|
||||
continue;
|
||||
|
||||
boolean allowed = false;
|
||||
for (String allowedOrigin : allowedOrigins)
|
||||
{
|
||||
if (allowedOrigin.equals(origin))
|
||||
if (allowedOrigin.contains("*"))
|
||||
{
|
||||
allowed = true;
|
||||
break;
|
||||
Matcher matcher = createMatcher(origin,allowedOrigin);
|
||||
if (matcher.matches())
|
||||
return true;
|
||||
}
|
||||
else if (allowedOrigin.equals(origin))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (!allowed)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private Matcher createMatcher(String origin, String allowedOrigin)
|
||||
{
|
||||
String regex = parseAllowedWildcardOriginToRegex(allowedOrigin);
|
||||
Pattern pattern = Pattern.compile(regex);
|
||||
return pattern.matcher(origin);
|
||||
}
|
||||
|
||||
private String parseAllowedWildcardOriginToRegex(String allowedOrigin)
|
||||
{
|
||||
String regex = allowedOrigin.replace(".","\\.");
|
||||
return regex.replace("*",".*"); // we want to be greedy here to match multiple subdomains, thus we use .*
|
||||
}
|
||||
|
||||
private boolean isSimpleRequest(HttpServletRequest request)
|
||||
|
|
|
@ -61,6 +61,13 @@ import org.eclipse.jetty.util.TypeUtil;
|
|||
* <p>
|
||||
* If the init parameter "delete" is set to "true", any files created will be deleted when the
|
||||
* current request returns.
|
||||
* <p>
|
||||
* The init parameter maxFormKeys sets the maximum number of keys that may be present in a
|
||||
* form (default set by system property org.eclipse.jetty.server.Request.maxFormKeys or 1000) to protect
|
||||
* against DOS attacks by bad hash keys.
|
||||
* <p>
|
||||
* The init parameter deleteFiles controls if uploaded files are automatically deleted after the request
|
||||
* completes.
|
||||
*
|
||||
* Use init parameter "maxFileSize" to set the max size file that can be uploaded.
|
||||
*
|
||||
|
@ -77,6 +84,7 @@ public class MultiPartFilter implements Filter
|
|||
private int _fileOutputBuffer = 0;
|
||||
private long _maxFileSize = -1L;
|
||||
private long _maxRequestSize = -1L;
|
||||
private int _maxFormKeys = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormKeys",1000).intValue();
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
/**
|
||||
|
@ -97,6 +105,9 @@ public class MultiPartFilter implements Filter
|
|||
_maxRequestSize = Long.parseLong(maxRequestSize.trim());
|
||||
|
||||
_context=filterConfig.getServletContext();
|
||||
String mfks = filterConfig.getInitParameter("maxFormKeys");
|
||||
if (mfks!=null)
|
||||
_maxFormKeys=Integer.parseInt(mfks);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------- */
|
||||
|
@ -138,8 +149,10 @@ public class MultiPartFilter implements Filter
|
|||
Collection<Part> parts = mpis.getParts();
|
||||
if (parts != null)
|
||||
{
|
||||
for (Part p:parts)
|
||||
Iterator<Part> itor = parts.iterator();
|
||||
while (itor.hasNext() && params.size() < _maxFormKeys)
|
||||
{
|
||||
Part p = itor.next();
|
||||
MultiPartInputStream.MultiPart mp = (MultiPartInputStream.MultiPart)p;
|
||||
if (mp.getFile() != null)
|
||||
{
|
||||
|
|
|
@ -57,12 +57,12 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
|||
|
||||
/**
|
||||
* Asynchronous Proxy Servlet.
|
||||
*
|
||||
*
|
||||
* Forward requests to another server either as a standard web proxy (as defined by RFC2616) or as a transparent proxy.
|
||||
* <p>
|
||||
* This servlet needs the jetty-util and jetty-client classes to be available to the web application.
|
||||
* <p>
|
||||
* To facilitate JMX monitoring, the "HttpClient", it's "ThreadPool" and the "Logger" are set as context attributes prefixed with the servlet name.
|
||||
* To facilitate JMX monitoring, the "HttpClient" and "ThreadPool" are set as context attributes prefixed with the servlet name.
|
||||
* <p>
|
||||
* The following init parameters may be used to configure the servlet:
|
||||
* <ul>
|
||||
|
@ -75,17 +75,15 @@ import org.eclipse.jetty.util.thread.QueuedThreadPool;
|
|||
* <li>requestBufferSize - the size of the request buffer (d. 12,288)
|
||||
* <li>responseHeaderSize - the size of the response header buffer (d. 6,144)
|
||||
* <li>responseBufferSize - the size of the response buffer (d. 32,768)
|
||||
* <li>HostHeader - Force the host header to a particular value
|
||||
* <li>HostHeader - Force the host header to a particular value
|
||||
* <li>whiteList - comma-separated list of allowed proxy destinations
|
||||
* <li>blackList - comma-separated list of forbidden proxy destinations
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* @see org.eclipse.jetty.server.handler.ConnectHandler
|
||||
*/
|
||||
public class ProxyServlet implements Servlet
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(ProxyServlet.class);
|
||||
|
||||
protected Logger _log;
|
||||
protected HttpClient _client;
|
||||
protected String _hostHeader;
|
||||
|
@ -111,25 +109,24 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.Servlet#init(javax.servlet.ServletConfig)
|
||||
*/
|
||||
public void init(ServletConfig config) throws ServletException
|
||||
{
|
||||
_config = config;
|
||||
_context = config.getServletContext();
|
||||
|
||||
|
||||
_hostHeader = config.getInitParameter("HostHeader");
|
||||
|
||||
try
|
||||
{
|
||||
_log = createLogger(config);
|
||||
_log = createLogger(config);
|
||||
|
||||
_client = createHttpClient(config);
|
||||
|
||||
|
||||
if (_context != null)
|
||||
{
|
||||
_context.setAttribute(config.getServletName() + ".Logger",_log);
|
||||
_context.setAttribute(config.getServletName() + ".ThreadPool",_client.getThreadPool());
|
||||
_context.setAttribute(config.getServletName() + ".HttpClient",_client);
|
||||
}
|
||||
|
@ -162,12 +159,12 @@ public class ProxyServlet implements Servlet
|
|||
_log.debug(x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create and return a logger based on the ServletConfig for use in the
|
||||
* Create and return a logger based on the ServletConfig for use in the
|
||||
* proxy servlet
|
||||
*
|
||||
*
|
||||
* @param config
|
||||
* @return Logger
|
||||
*/
|
||||
|
@ -175,24 +172,24 @@ public class ProxyServlet implements Servlet
|
|||
{
|
||||
return Log.getLogger("org.eclipse.jetty.servlets." + config.getServletName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Create and return an HttpClient based on ServletConfig
|
||||
*
|
||||
* By default this implementation will create an instance of the
|
||||
*
|
||||
* By default this implementation will create an instance of the
|
||||
* HttpClient for use by this proxy servlet.
|
||||
*
|
||||
* @param config
|
||||
* @return HttpClient
|
||||
*
|
||||
* @param config
|
||||
* @return HttpClient
|
||||
* @throws Exception
|
||||
*/
|
||||
protected HttpClient createHttpClient(ServletConfig config) throws Exception
|
||||
{
|
||||
HttpClient client = new HttpClient();
|
||||
client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);
|
||||
|
||||
|
||||
String t = config.getInitParameter("maxThreads");
|
||||
|
||||
|
||||
if (t != null)
|
||||
{
|
||||
client.setThreadPool(new QueuedThreadPool(Integer.parseInt(t)));
|
||||
|
@ -201,67 +198,67 @@ public class ProxyServlet implements Servlet
|
|||
{
|
||||
client.setThreadPool(new QueuedThreadPool());
|
||||
}
|
||||
|
||||
((QueuedThreadPool)client.getThreadPool()).setName(config.getServletName());
|
||||
|
||||
((QueuedThreadPool)client.getThreadPool()).setName(config.getServletName());
|
||||
|
||||
t = config.getInitParameter("maxConnections");
|
||||
|
||||
|
||||
if (t != null)
|
||||
{
|
||||
client.setMaxConnectionsPerAddress(Integer.parseInt(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("timeout");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setTimeout(Long.parseLong(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("idleTimeout");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setIdleTimeout(Long.parseLong(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("requestHeaderSize");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setRequestHeaderSize(Integer.parseInt(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("requestBufferSize");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setRequestBufferSize(Integer.parseInt(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("responseHeaderSize");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setResponseHeaderSize(Integer.parseInt(t));
|
||||
}
|
||||
|
||||
|
||||
t = config.getInitParameter("responseBufferSize");
|
||||
|
||||
|
||||
if ( t != null )
|
||||
{
|
||||
client.setResponseBufferSize(Integer.parseInt(t));
|
||||
}
|
||||
|
||||
|
||||
client.start();
|
||||
|
||||
|
||||
return client;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Helper function to process a parameter value containing a list of new entries and initialize the specified host map.
|
||||
*
|
||||
*
|
||||
* @param list
|
||||
* comma-separated list of new entries
|
||||
* @param hostMap
|
||||
|
@ -301,7 +298,7 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Check the request hostname and path against white- and blacklist.
|
||||
*
|
||||
*
|
||||
* @param host
|
||||
* hostname to check
|
||||
* @param path
|
||||
|
@ -353,7 +350,7 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.Servlet#getServletConfig()
|
||||
*/
|
||||
public ServletConfig getServletConfig()
|
||||
|
@ -364,7 +361,7 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Get the hostHeader.
|
||||
*
|
||||
*
|
||||
* @return the hostHeader
|
||||
*/
|
||||
public String getHostHeader()
|
||||
|
@ -375,7 +372,7 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Set the hostHeader.
|
||||
*
|
||||
*
|
||||
* @param hostHeader
|
||||
* the hostHeader to set
|
||||
*/
|
||||
|
@ -387,7 +384,7 @@ public class ProxyServlet implements Servlet
|
|||
/* ------------------------------------------------------------ */
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.Servlet#service(javax.servlet.ServletRequest, javax.servlet.ServletResponse)
|
||||
*/
|
||||
public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
|
||||
|
@ -412,7 +409,7 @@ public class ProxyServlet implements Servlet
|
|||
response.sendError(HttpServletResponse.SC_GATEWAY_TIMEOUT); // Need better test that isInitial
|
||||
else
|
||||
{
|
||||
|
||||
|
||||
String uri = request.getRequestURI();
|
||||
if (request.getQueryString() != null)
|
||||
uri += "?" + request.getQueryString();
|
||||
|
@ -430,14 +427,17 @@ public class ProxyServlet implements Servlet
|
|||
|
||||
HttpExchange exchange = new HttpExchange()
|
||||
{
|
||||
@Override
|
||||
protected void onRequestCommitted() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onRequestComplete() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseComplete() throws IOException
|
||||
{
|
||||
if (debug != 0)
|
||||
|
@ -445,6 +445,7 @@ public class ProxyServlet implements Servlet
|
|||
continuation.complete();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseContent(Buffer content) throws IOException
|
||||
{
|
||||
if (debug != 0)
|
||||
|
@ -452,10 +453,12 @@ public class ProxyServlet implements Servlet
|
|||
content.writeTo(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseHeaderComplete() throws IOException
|
||||
{
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException
|
||||
{
|
||||
if (debug != 0)
|
||||
|
@ -467,6 +470,7 @@ public class ProxyServlet implements Servlet
|
|||
response.setStatus(status);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResponseHeader(Buffer name, Buffer value) throws IOException
|
||||
{
|
||||
String s = name.toString().toLowerCase();
|
||||
|
@ -481,11 +485,12 @@ public class ProxyServlet implements Servlet
|
|||
_log.debug(debug + " " + name + "! " + value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onConnectionFailed(Throwable ex)
|
||||
{
|
||||
handleOnConnectionFailed(ex,request,response);
|
||||
|
||||
// it is possible this might trigger before the
|
||||
|
||||
// it is possible this might trigger before the
|
||||
// continuation.suspend()
|
||||
if (!continuation.isInitial())
|
||||
{
|
||||
|
@ -493,16 +498,17 @@ public class ProxyServlet implements Servlet
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Throwable ex)
|
||||
{
|
||||
if (ex instanceof EofException)
|
||||
{
|
||||
LOG.ignore(ex);
|
||||
_log.ignore(ex);
|
||||
return;
|
||||
}
|
||||
handleOnException(ex,request,response);
|
||||
|
||||
// it is possible this might trigger before the
|
||||
|
||||
// it is possible this might trigger before the
|
||||
// continuation.suspend()
|
||||
if (!continuation.isInitial())
|
||||
{
|
||||
|
@ -510,6 +516,7 @@ public class ProxyServlet implements Servlet
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onExpire()
|
||||
{
|
||||
handleOnExpire(request,response);
|
||||
|
@ -597,14 +604,14 @@ public class ProxyServlet implements Servlet
|
|||
if (hasContent)
|
||||
exchange.setRequestContentSource(in);
|
||||
|
||||
customizeExchange(exchange, request);
|
||||
|
||||
customizeExchange(exchange, request);
|
||||
|
||||
/*
|
||||
* we need to set the timeout on the continuation to take into
|
||||
* account the timeout of the HttpClient and the HttpExchange
|
||||
*/
|
||||
long ctimeout = (_client.getTimeout() > exchange.getTimeout()) ? _client.getTimeout() : exchange.getTimeout();
|
||||
|
||||
|
||||
// continuation fudge factor of 1000, underlying components
|
||||
// should fail/expire first from exchange
|
||||
if ( ctimeout == 0 )
|
||||
|
@ -612,12 +619,12 @@ public class ProxyServlet implements Servlet
|
|||
continuation.setTimeout(0); // ideally never times out
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
continuation.setTimeout(ctimeout + 1000);
|
||||
}
|
||||
|
||||
|
||||
customizeContinuation(continuation);
|
||||
|
||||
|
||||
continuation.suspend(response);
|
||||
_client.send(exchange);
|
||||
|
||||
|
@ -678,7 +685,7 @@ public class ProxyServlet implements Servlet
|
|||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see javax.servlet.Servlet#getServletInfo()
|
||||
*/
|
||||
public String getServletInfo()
|
||||
|
@ -689,7 +696,7 @@ public class ProxyServlet implements Servlet
|
|||
|
||||
/**
|
||||
* Extension point for subclasses to customize an exchange. Useful for setting timeouts etc. The default implementation does nothing.
|
||||
*
|
||||
*
|
||||
* @param exchange
|
||||
* @param request
|
||||
*/
|
||||
|
@ -701,7 +708,7 @@ public class ProxyServlet implements Servlet
|
|||
/**
|
||||
* Extension point for subclasses to customize the Continuation after it's initial creation in the service method. Useful for setting timeouts etc. The
|
||||
* default implementation does nothing.
|
||||
*
|
||||
*
|
||||
* @param continuation
|
||||
*/
|
||||
protected void customizeContinuation(Continuation continuation)
|
||||
|
@ -712,7 +719,7 @@ public class ProxyServlet implements Servlet
|
|||
/**
|
||||
* Extension point for custom handling of an HttpExchange's onConnectionFailed method. The default implementation delegates to
|
||||
* {@link #handleOnException(Throwable, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)}
|
||||
*
|
||||
*
|
||||
* @param ex
|
||||
* @param request
|
||||
* @param response
|
||||
|
@ -725,15 +732,15 @@ public class ProxyServlet implements Servlet
|
|||
/**
|
||||
* Extension point for custom handling of an HttpExchange's onException method. The default implementation sets the response status to
|
||||
* HttpServletResponse.SC_INTERNAL_SERVER_ERROR (503)
|
||||
*
|
||||
*
|
||||
* @param ex
|
||||
* @param request
|
||||
* @param response
|
||||
*/
|
||||
protected void handleOnException(Throwable ex, HttpServletRequest request, HttpServletResponse response)
|
||||
{
|
||||
LOG.warn(ex.toString());
|
||||
LOG.debug(ex);
|
||||
_log.warn(ex.toString());
|
||||
_log.debug(ex);
|
||||
if (!response.isCommitted())
|
||||
{
|
||||
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||
|
@ -743,7 +750,7 @@ public class ProxyServlet implements Servlet
|
|||
/**
|
||||
* Extension point for custom handling of an HttpExchange's onExpire method. The default implementation sets the response status to
|
||||
* HttpServletResponse.SC_GATEWAY_TIMEOUT (504)
|
||||
*
|
||||
*
|
||||
* @param request
|
||||
* @param response
|
||||
*/
|
||||
|
@ -757,7 +764,7 @@ public class ProxyServlet implements Servlet
|
|||
|
||||
/**
|
||||
* Transparent Proxy.
|
||||
*
|
||||
*
|
||||
* This convenience extension to ProxyServlet configures the servlet as a transparent proxy. The servlet is configured with init parameters:
|
||||
* <ul>
|
||||
* <li>ProxyTo - a URI like http://host:80/context to which the request is proxied.
|
||||
|
@ -765,7 +772,7 @@ public class ProxyServlet implements Servlet
|
|||
* </ul>
|
||||
* For example, if a request was received at /foo/bar and the ProxyTo was http://host:80/context and the Prefix was /foo, then the request would be proxied
|
||||
* to http://host:80/context/bar
|
||||
*
|
||||
*
|
||||
*/
|
||||
public static class Transparent extends ProxyServlet
|
||||
{
|
||||
|
|
|
@ -79,6 +79,52 @@ public class CrossOriginFilterTest
|
|||
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleRequestWithMatchingWildcardOrigin() throws Exception
|
||||
{
|
||||
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
|
||||
String origin = "http://subdomain.example.com";
|
||||
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://*.example.com");
|
||||
tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
|
||||
|
||||
String request = "" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Origin: " + origin + "\r\n" +
|
||||
"\r\n";
|
||||
String response = tester.getResponses(request);
|
||||
Assert.assertTrue(response.contains("HTTP/1.1 200"));
|
||||
Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER));
|
||||
Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER));
|
||||
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleRequestWithMatchingWildcardOriginAndMultipleSubdomains() throws Exception
|
||||
{
|
||||
FilterHolder filterHolder = new FilterHolder(new CrossOriginFilter());
|
||||
String origin = "http://subdomain.subdomain.example.com";
|
||||
filterHolder.setInitParameter(CrossOriginFilter.ALLOWED_ORIGINS_PARAM, "http://*.example.com");
|
||||
tester.getContext().addFilter(filterHolder, "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
tester.getContext().addServlet(new ServletHolder(new ResourceServlet(latch)), "/*");
|
||||
|
||||
String request = "" +
|
||||
"GET / HTTP/1.1\r\n" +
|
||||
"Host: localhost\r\n" +
|
||||
"Origin: " + origin + "\r\n" +
|
||||
"\r\n";
|
||||
String response = tester.getResponses(request);
|
||||
Assert.assertTrue(response.contains("HTTP/1.1 200"));
|
||||
Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_ORIGIN_HEADER));
|
||||
Assert.assertTrue(response.contains(CrossOriginFilter.ACCESS_CONTROL_ALLOW_CREDENTIALS_HEADER));
|
||||
Assert.assertTrue(latch.await(1, TimeUnit.SECONDS));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleRequestWithMatchingOrigin() throws Exception
|
||||
{
|
||||
|
@ -330,6 +376,7 @@ public class CrossOriginFilterTest
|
|||
|
||||
public static class ResourceServlet extends HttpServlet
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final CountDownLatch latch;
|
||||
|
||||
public ResourceServlet(CountDownLatch latch)
|
||||
|
|
|
@ -20,6 +20,7 @@ import java.io.FileInputStream;
|
|||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileReader;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
|
@ -30,7 +31,6 @@ import java.lang.reflect.Method;
|
|||
import java.net.ConnectException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.security.Policy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
|
@ -40,17 +40,15 @@ import java.util.List;
|
|||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/*-------------------------------------------*/
|
||||
/**
|
||||
* <p>
|
||||
* Main start class. This class is intended to be the main class listed in the MANIFEST.MF of the start.jar archive. It
|
||||
* allows an application to be started with the command "java -jar start.jar".
|
||||
* Main start class. This class is intended to be the main class listed in the MANIFEST.MF of the start.jar archive. It allows an application to be started with
|
||||
* the command "java -jar start.jar".
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>
|
||||
* The behaviour of Main is controlled by the parsing of the {@link Config} "org/eclipse/start/start.config" file
|
||||
* obtained as a resource or file.
|
||||
* The behaviour of Main is controlled by the parsing of the {@link Config} "org/eclipse/start/start.config" file obtained as a resource or file.
|
||||
* </p>
|
||||
*/
|
||||
public class Main
|
||||
|
@ -67,257 +65,245 @@ public class Main
|
|||
private boolean _dryRun = false;
|
||||
private boolean _exec = false;
|
||||
private final Config _config = new Config();
|
||||
private Set<String> _sysProps = new HashSet<String>();
|
||||
private List<String> _jvmArgs = new ArrayList<String>();
|
||||
private final Set<String> _sysProps = new HashSet<String>();
|
||||
private final List<String> _jvmArgs = new ArrayList<String>();
|
||||
private String _startConfig = null;
|
||||
|
||||
private String _jettyHome;
|
||||
|
||||
public static void main(String[] args)
|
||||
{
|
||||
Main main = new Main();
|
||||
main.parseCommandLine(args);
|
||||
}
|
||||
|
||||
public void parseCommandLine(String[] args)
|
||||
public static void main(String[] args)
|
||||
{
|
||||
try
|
||||
{
|
||||
List<String> arguments = new ArrayList<String>();
|
||||
|
||||
// add the command line args and look for start.ini args
|
||||
boolean ini=false;
|
||||
for (String arg : args)
|
||||
{
|
||||
if (arg.startsWith("--ini=")||arg.equals("--ini"))
|
||||
{
|
||||
ini=true;
|
||||
if (arg.length()>6)
|
||||
{
|
||||
arguments.addAll(loadStartIni(arg.substring(6)));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (arg.startsWith("--config="))
|
||||
{
|
||||
_startConfig=arg.substring(9);
|
||||
}
|
||||
else
|
||||
{
|
||||
arguments.add(arg);
|
||||
}
|
||||
}
|
||||
|
||||
// if no non-option inis, add the start.ini
|
||||
if (!ini)
|
||||
{
|
||||
arguments.addAll(0,loadStartIni(null));
|
||||
}
|
||||
|
||||
// The XML Configuration Files to initialize with
|
||||
List<String> xmls = new ArrayList<String>();
|
||||
|
||||
// Process the arguments
|
||||
int startup=0;
|
||||
for (String arg : arguments)
|
||||
{
|
||||
if ("--help".equals(arg) || "-?".equals(arg))
|
||||
{
|
||||
_showUsage = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("--stop".equals(arg))
|
||||
{
|
||||
int port = Integer.parseInt(Config.getProperty("STOP.PORT","-1"));
|
||||
String key = Config.getProperty("STOP.KEY",null);
|
||||
stop(port,key);
|
||||
return;
|
||||
}
|
||||
|
||||
if ("--version".equals(arg) || "-v".equals(arg) || "--info".equals(arg))
|
||||
{
|
||||
_dumpVersions = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("--list-modes".equals(arg) || "--list-options".equals(arg))
|
||||
{
|
||||
_listOptions = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("--list-config".equals(arg))
|
||||
{
|
||||
_listConfig=true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("--exec-print".equals(arg)||"--dry-run".equals(arg))
|
||||
{
|
||||
_dryRun = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("--exec".equals(arg))
|
||||
{
|
||||
_exec = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special internal indicator that jetty was started by the jetty.sh Daemon
|
||||
if ("--daemon".equals(arg))
|
||||
{
|
||||
File startDir = new File(System.getProperty("jetty.logs","logs"));
|
||||
if (!startDir.exists() || !startDir.canWrite() )
|
||||
startDir = new File(".");
|
||||
File startLog = new File(startDir,"start.log");
|
||||
if (!startLog.exists() && !startLog.createNewFile())
|
||||
{
|
||||
// Output about error is lost in majority of cases.
|
||||
System.err.println("Unable to create: " + startLog.getAbsolutePath());
|
||||
// Toss a unique exit code indicating this failure.
|
||||
usageExit(ERR_LOGGING);
|
||||
}
|
||||
|
||||
if (!startLog.canWrite())
|
||||
{
|
||||
// Output about error is lost in majority of cases.
|
||||
System.err.println("Unable to write to: " + startLog.getAbsolutePath());
|
||||
// Toss a unique exit code indicating this failure.
|
||||
usageExit(ERR_LOGGING);
|
||||
}
|
||||
PrintStream logger = new PrintStream(new FileOutputStream(startLog,false));
|
||||
System.setOut(logger);
|
||||
System.setErr(logger);
|
||||
System.out.println("Establishing start.log on " + new Date());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg.startsWith("--pre="))
|
||||
{
|
||||
xmls.add(startup++,arg.substring(6));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg.startsWith("-D"))
|
||||
{
|
||||
String[] assign = arg.substring(2).split("=",2);
|
||||
_sysProps.add(assign[0]);
|
||||
switch(assign.length)
|
||||
{
|
||||
case 2:
|
||||
System.setProperty(assign[0],assign[1]);
|
||||
break;
|
||||
case 1:
|
||||
System.setProperty(assign[0],"");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg.startsWith("-"))
|
||||
{
|
||||
_jvmArgs.add(arg);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is this a Property?
|
||||
if (arg.indexOf('=') >= 0)
|
||||
{
|
||||
String[] assign = arg.split("=",2);
|
||||
|
||||
switch(assign.length)
|
||||
{
|
||||
case 2:
|
||||
if ("OPTIONS".equals(assign[0]))
|
||||
{
|
||||
String opts[] = assign[1].split(",");
|
||||
for (String opt : opts)
|
||||
_config.addActiveOption(opt);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._config.setProperty(assign[0],assign[1]);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
this._config.setProperty(assign[0],null);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Anything else is considered an XML file.
|
||||
if (xmls.contains(arg))
|
||||
{
|
||||
System.out.println("WARN: Argument '"+arg+"' specified multiple times. Check start.ini?");
|
||||
System.out.println("Use \"java -jar start.jar --help\" for more information.");
|
||||
}
|
||||
xmls.add(arg);
|
||||
}
|
||||
|
||||
start(xmls);
|
||||
Main main = new Main();
|
||||
List<String> arguments = main.expandCommandLine(args);
|
||||
List<String> xmls = main.processCommandLine(arguments);
|
||||
if (xmls!=null)
|
||||
main.start(xmls);
|
||||
}
|
||||
catch (Throwable t)
|
||||
{
|
||||
usageExit(t,ERR_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If a start.ini is present in the CWD, then load it into the argument list.
|
||||
*/
|
||||
private List<String> loadStartIni(String ini)
|
||||
{
|
||||
String jettyHome=System.getProperty("jetty.home");
|
||||
File startIniFile = ini==null?((jettyHome!=null)? new File(jettyHome,"start.ini"):new File("start.ini")):new File(ini);
|
||||
if (!startIniFile.exists())
|
||||
{
|
||||
if (ini != null)
|
||||
{
|
||||
System.err.println("Warning - can't find ini file: " + ini);
|
||||
}
|
||||
// No start.ini found, skip load.
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<String> args = new ArrayList<String>();
|
||||
|
||||
FileReader reader = null;
|
||||
BufferedReader buf = null;
|
||||
try
|
||||
{
|
||||
reader = new FileReader(startIniFile);
|
||||
buf = new BufferedReader(reader);
|
||||
|
||||
String arg;
|
||||
while ((arg = buf.readLine()) != null)
|
||||
{
|
||||
arg = arg.trim();
|
||||
if (arg.length() == 0 || arg.startsWith("#"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
args.add(arg);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
catch (Throwable e)
|
||||
{
|
||||
usageExit(e,ERR_UNKNOWN);
|
||||
}
|
||||
finally
|
||||
}
|
||||
|
||||
Main() throws IOException
|
||||
{
|
||||
_jettyHome = System.getProperty("jetty.home",".");
|
||||
_jettyHome = new File(_jettyHome).getCanonicalPath();
|
||||
}
|
||||
|
||||
public List<String> expandCommandLine(String[] args) throws Exception
|
||||
{
|
||||
List<String> arguments = new ArrayList<String>();
|
||||
|
||||
// add the command line args and look for start.ini args
|
||||
boolean ini = false;
|
||||
for (String arg : args)
|
||||
{
|
||||
close(buf);
|
||||
close(reader);
|
||||
if (arg.startsWith("--ini=") || arg.equals("--ini"))
|
||||
{
|
||||
ini = true;
|
||||
if (arg.length() > 6)
|
||||
{
|
||||
arguments.addAll(loadStartIni(new File(arg.substring(6))));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (arg.startsWith("--config="))
|
||||
{
|
||||
_startConfig = arg.substring(9);
|
||||
}
|
||||
else
|
||||
{
|
||||
arguments.add(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return args;
|
||||
// if no non-option inis, add the start.ini and start.d
|
||||
if (!ini)
|
||||
{
|
||||
arguments.addAll(0,parseStartIniFiles());
|
||||
}
|
||||
|
||||
return arguments;
|
||||
}
|
||||
|
||||
List<String> parseStartIniFiles()
|
||||
{
|
||||
List<String> ini_args=new ArrayList<String>();
|
||||
File start_ini = new File(_jettyHome,"start.ini");
|
||||
if (start_ini.exists())
|
||||
ini_args.addAll(loadStartIni(start_ini));
|
||||
|
||||
File start_d = new File(_jettyHome,"start.d");
|
||||
if (start_d.isDirectory())
|
||||
{
|
||||
File[] inis = start_d.listFiles(new FilenameFilter()
|
||||
{
|
||||
public boolean accept(File dir, String name)
|
||||
{
|
||||
return name.toLowerCase().endsWith(".ini");
|
||||
}
|
||||
});
|
||||
Arrays.sort(inis);
|
||||
for (File i : inis)
|
||||
ini_args.addAll(loadStartIni(i));
|
||||
}
|
||||
return ini_args;
|
||||
}
|
||||
|
||||
public List<String> processCommandLine(List<String> arguments) throws Exception
|
||||
{
|
||||
// The XML Configuration Files to initialize with
|
||||
List<String> xmls = new ArrayList<String>();
|
||||
|
||||
// Process the arguments
|
||||
int startup = 0;
|
||||
for (String arg : arguments)
|
||||
{
|
||||
if ("--help".equals(arg) || "-?".equals(arg))
|
||||
{
|
||||
_showUsage = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("--stop".equals(arg))
|
||||
{
|
||||
int port = Integer.parseInt(Config.getProperty("STOP.PORT","-1"));
|
||||
String key = Config.getProperty("STOP.KEY",null);
|
||||
stop(port,key);
|
||||
return null;
|
||||
}
|
||||
|
||||
if ("--version".equals(arg) || "-v".equals(arg) || "--info".equals(arg))
|
||||
{
|
||||
_dumpVersions = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("--list-modes".equals(arg) || "--list-options".equals(arg))
|
||||
{
|
||||
_listOptions = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("--list-config".equals(arg))
|
||||
{
|
||||
_listConfig = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("--exec-print".equals(arg) || "--dry-run".equals(arg))
|
||||
{
|
||||
_dryRun = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ("--exec".equals(arg))
|
||||
{
|
||||
_exec = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Special internal indicator that jetty was started by the jetty.sh Daemon
|
||||
if ("--daemon".equals(arg))
|
||||
{
|
||||
File startDir = new File(System.getProperty("jetty.logs","logs"));
|
||||
if (!startDir.exists() || !startDir.canWrite())
|
||||
startDir = new File(".");
|
||||
File startLog = new File(startDir,"start.log");
|
||||
if (!startLog.exists() && !startLog.createNewFile())
|
||||
{
|
||||
// Output about error is lost in majority of cases.
|
||||
System.err.println("Unable to create: " + startLog.getAbsolutePath());
|
||||
// Toss a unique exit code indicating this failure.
|
||||
usageExit(ERR_LOGGING);
|
||||
}
|
||||
|
||||
if (!startLog.canWrite())
|
||||
{
|
||||
// Output about error is lost in majority of cases.
|
||||
System.err.println("Unable to write to: " + startLog.getAbsolutePath());
|
||||
// Toss a unique exit code indicating this failure.
|
||||
usageExit(ERR_LOGGING);
|
||||
}
|
||||
PrintStream logger = new PrintStream(new FileOutputStream(startLog,false));
|
||||
System.setOut(logger);
|
||||
System.setErr(logger);
|
||||
System.out.println("Establishing start.log on " + new Date());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg.startsWith("--pre="))
|
||||
{
|
||||
xmls.add(startup++,arg.substring(6));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg.startsWith("-D"))
|
||||
{
|
||||
String[] assign = arg.substring(2).split("=",2);
|
||||
_sysProps.add(assign[0]);
|
||||
switch (assign.length)
|
||||
{
|
||||
case 2:
|
||||
System.setProperty(assign[0],assign[1]);
|
||||
break;
|
||||
case 1:
|
||||
System.setProperty(assign[0],"");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (arg.startsWith("-"))
|
||||
{
|
||||
_jvmArgs.add(arg);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is this a Property?
|
||||
if (arg.indexOf('=') >= 0)
|
||||
{
|
||||
String[] assign = arg.split("=",2);
|
||||
|
||||
switch (assign.length)
|
||||
{
|
||||
case 2:
|
||||
if ("OPTIONS".equals(assign[0]))
|
||||
{
|
||||
String opts[] = assign[1].split(",");
|
||||
for (String opt : opts)
|
||||
_config.addActiveOption(opt);
|
||||
}
|
||||
else
|
||||
{
|
||||
this._config.setProperty(assign[0],assign[1]);
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
this._config.setProperty(assign[0],null);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Anything else is considered an XML file.
|
||||
if (xmls.contains(arg))
|
||||
{
|
||||
System.out.println("WARN: Argument '" + arg + "' specified multiple times. Check start.ini?");
|
||||
System.out.println("Use \"java -jar start.jar --help\" for more information.");
|
||||
}
|
||||
xmls.add(arg);
|
||||
}
|
||||
|
||||
return xmls;
|
||||
}
|
||||
|
||||
private void usage()
|
||||
|
@ -339,10 +325,10 @@ public class Main
|
|||
|
||||
while ((line = buf.readLine()) != null)
|
||||
{
|
||||
if (line.endsWith("@") && line.indexOf('@')!=line.lastIndexOf('@'))
|
||||
if (line.endsWith("@") && line.indexOf('@') != line.lastIndexOf('@'))
|
||||
{
|
||||
String indent=line.substring(0,line.indexOf("@"));
|
||||
String info=line.substring(line.indexOf('@'),line.lastIndexOf('@'));
|
||||
String indent = line.substring(0,line.indexOf("@"));
|
||||
String info = line.substring(line.indexOf('@'),line.lastIndexOf('@'));
|
||||
|
||||
if (info.equals("@OPTIONS"))
|
||||
{
|
||||
|
@ -352,7 +338,7 @@ public class Main
|
|||
|
||||
for (String option : sortedOptions)
|
||||
{
|
||||
if ("*".equals(option) || option.trim().length()==0)
|
||||
if ("*".equals(option) || option.trim().length() == 0)
|
||||
continue;
|
||||
System.out.print(indent);
|
||||
System.out.println(option);
|
||||
|
@ -396,7 +382,7 @@ public class Main
|
|||
else if (info.equals("@STARTINI"))
|
||||
{
|
||||
List<String> ini = loadStartIni(null);
|
||||
if (ini!=null && ini.size()>0)
|
||||
if (ini != null && ini.size() > 0)
|
||||
{
|
||||
for (String a : ini)
|
||||
{
|
||||
|
@ -429,7 +415,7 @@ public class Main
|
|||
}
|
||||
|
||||
public void invokeMain(ClassLoader classloader, String classname, List<String> args) throws IllegalAccessException, InvocationTargetException,
|
||||
NoSuchMethodException, ClassNotFoundException
|
||||
NoSuchMethodException, ClassNotFoundException
|
||||
{
|
||||
Class<?> invoked_class = null;
|
||||
|
||||
|
@ -462,10 +448,12 @@ public class Main
|
|||
|
||||
String argArray[] = args.toArray(new String[0]);
|
||||
|
||||
Class<?>[] method_param_types = new Class[] { argArray.getClass() };
|
||||
Class<?>[] method_param_types = new Class[]
|
||||
{ argArray.getClass() };
|
||||
|
||||
Method main = invoked_class.getDeclaredMethod("main",method_param_types);
|
||||
Object[] method_params = new Object[] { argArray };
|
||||
Object[] method_params = new Object[]
|
||||
{ argArray };
|
||||
main.invoke(null,method_params);
|
||||
}
|
||||
|
||||
|
@ -492,13 +480,12 @@ public class Main
|
|||
// Setup Start / Stop Monitoring
|
||||
int port = Integer.parseInt(Config.getProperty("STOP.PORT","-1"));
|
||||
String key = Config.getProperty("STOP.KEY",null);
|
||||
Monitor monitor=new Monitor(port,key);
|
||||
|
||||
Monitor monitor = new Monitor(port,key);
|
||||
|
||||
// Load potential Config (start.config)
|
||||
List<String> configuredXmls = loadConfig(xmls);
|
||||
|
||||
// No XML defined in start.config or command line. Can't execute.
|
||||
// No XML defined in start.config or command line. Can't execute.
|
||||
if (configuredXmls.isEmpty())
|
||||
{
|
||||
throw new FileNotFoundException("No XML configuration files specified in start.config or command line.");
|
||||
|
@ -523,7 +510,7 @@ public class Main
|
|||
System.err.println("classloader.parent=" + cl.getParent());
|
||||
System.err.println("properties=" + Config.getProperties());
|
||||
}
|
||||
|
||||
|
||||
// Show the usage information and return
|
||||
if (_showUsage)
|
||||
{
|
||||
|
@ -544,7 +531,7 @@ public class Main
|
|||
showAllOptionsWithVersions(classpath);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_listConfig)
|
||||
{
|
||||
listConfig();
|
||||
|
@ -557,7 +544,7 @@ public class Main
|
|||
System.out.println(buildCommandLine(classpath,configuredXmls));
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// execute Jetty in another JVM
|
||||
if (_exec)
|
||||
{
|
||||
|
@ -565,11 +552,12 @@ public class Main
|
|||
final Process process = Runtime.getRuntime().exec(cmd);
|
||||
Runtime.getRuntime().addShutdownHook(new Thread()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
Config.debug("Destroying " + process);
|
||||
process.destroy();
|
||||
}
|
||||
}
|
||||
});
|
||||
copyInThread(process.getErrorStream(),System.err);
|
||||
copyInThread(process.getInputStream(),System.out);
|
||||
|
@ -578,7 +566,7 @@ public class Main
|
|||
process.waitFor();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (_jvmArgs.size() > 0 || _sysProps.size() > 0)
|
||||
{
|
||||
System.err.println("WARNING: System properties and/or JVM args set. Consider using --dry-run or --exec");
|
||||
|
@ -617,7 +605,7 @@ public class Main
|
|||
}
|
||||
}
|
||||
|
||||
private void copyInThread(final InputStream in,final OutputStream out)
|
||||
private void copyInThread(final InputStream in, final OutputStream out)
|
||||
{
|
||||
new Thread(new Runnable()
|
||||
{
|
||||
|
@ -625,23 +613,23 @@ public class Main
|
|||
{
|
||||
try
|
||||
{
|
||||
byte[] buf=new byte[1024];
|
||||
int len=in.read(buf);
|
||||
while(len>0)
|
||||
byte[] buf = new byte[1024];
|
||||
int len = in.read(buf);
|
||||
while (len > 0)
|
||||
{
|
||||
out.write(buf,0,len);
|
||||
len=in.read(buf);
|
||||
len = in.read(buf);
|
||||
}
|
||||
}
|
||||
catch(IOException e)
|
||||
catch (IOException e)
|
||||
{
|
||||
// e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
private String resolveXmlConfig(String xmlFilename) throws FileNotFoundException
|
||||
{
|
||||
if (!xmlFilename.toLowerCase().endsWith(".xml"))
|
||||
|
@ -675,22 +663,22 @@ public class Main
|
|||
{
|
||||
StringBuilder cmd = new StringBuilder();
|
||||
cmd.append(findJavaBin());
|
||||
for (String x:_jvmArgs)
|
||||
for (String x : _jvmArgs)
|
||||
cmd.append(' ').append(x);
|
||||
cmd.append(" -Djetty.home=").append(_jettyHome);
|
||||
for (String p:_sysProps)
|
||||
for (String p : _sysProps)
|
||||
{
|
||||
cmd.append(" -D").append(p);
|
||||
String v=System.getProperty(p);
|
||||
if (v!=null && v.length()>0)
|
||||
String v = System.getProperty(p);
|
||||
if (v != null && v.length() > 0)
|
||||
cmd.append('=').append(v);
|
||||
}
|
||||
cmd.append(" -cp ").append(classpath.toString());
|
||||
cmd.append(" ").append(_config.getMainClassname());
|
||||
|
||||
|
||||
// Check if we need to pass properties as a file
|
||||
Properties properties = Config.getProperties();
|
||||
if (properties.size()>0)
|
||||
if (properties.size() > 0)
|
||||
{
|
||||
File prop_file = File.createTempFile("start",".properties");
|
||||
if (!_dryRun)
|
||||
|
@ -698,7 +686,7 @@ public class Main
|
|||
properties.store(new FileOutputStream(prop_file),"start.jar properties");
|
||||
cmd.append(" ").append(prop_file.getAbsolutePath());
|
||||
}
|
||||
|
||||
|
||||
for (String xml : xmls)
|
||||
{
|
||||
cmd.append(' ').append(xml);
|
||||
|
@ -875,11 +863,10 @@ public class Main
|
|||
|
||||
private String getZipVersion(File element)
|
||||
{
|
||||
// TODO - find version in zip file. Look for META-INF/MANIFEST.MF ?
|
||||
// TODO - find version in zip file. Look for META-INF/MANIFEST.MF ?
|
||||
return "";
|
||||
}
|
||||
|
||||
|
||||
private List<String> resolveXmlConfigs(List<String> xmls) throws FileNotFoundException
|
||||
{
|
||||
List<String> ret = new ArrayList<String>();
|
||||
|
@ -896,15 +883,15 @@ public class Main
|
|||
InputStream cfgstream = null;
|
||||
try
|
||||
{
|
||||
cfgstream=getConfigStream();
|
||||
byte[] buf=new byte[4096];
|
||||
|
||||
int len=0;
|
||||
|
||||
while (len>=0)
|
||||
cfgstream = getConfigStream();
|
||||
byte[] buf = new byte[4096];
|
||||
|
||||
int len = 0;
|
||||
|
||||
while (len >= 0)
|
||||
{
|
||||
len=cfgstream.read(buf);
|
||||
if (len>0)
|
||||
len = cfgstream.read(buf);
|
||||
if (len > 0)
|
||||
System.out.write(buf,0,len);
|
||||
}
|
||||
}
|
||||
|
@ -917,13 +904,13 @@ public class Main
|
|||
close(cfgstream);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load Configuration.
|
||||
*
|
||||
* No specific configuration is real until a {@link Config#getCombinedClasspath(java.util.Collection)} is used to
|
||||
* execute the {@link Class} specified by {@link Config#getMainClassname()} is executed.
|
||||
*
|
||||
*
|
||||
* No specific configuration is real until a {@link Config#getCombinedClasspath(java.util.Collection)} is used to execute the {@link Class} specified by
|
||||
* {@link Config#getMainClassname()} is executed.
|
||||
*
|
||||
* @param xmls
|
||||
* the command line specified xml configuration options.
|
||||
* @return the list of xml configurations arriving via command line and start.config choices.
|
||||
|
@ -935,13 +922,13 @@ public class Main
|
|||
{
|
||||
// Pass in xmls.size into Config so that conditions based on "nargs" work.
|
||||
_config.setArgCount(xmls.size());
|
||||
|
||||
cfgstream=getConfigStream();
|
||||
|
||||
|
||||
cfgstream = getConfigStream();
|
||||
|
||||
// parse the config
|
||||
_config.parse(cfgstream);
|
||||
|
||||
_jettyHome = Config.getProperty("jetty.home");
|
||||
|
||||
_jettyHome = Config.getProperty("jetty.home",_jettyHome);
|
||||
if (_jettyHome != null)
|
||||
{
|
||||
_jettyHome = new File(_jettyHome).getCanonicalPath();
|
||||
|
@ -975,12 +962,12 @@ public class Main
|
|||
|
||||
private InputStream getConfigStream() throws FileNotFoundException
|
||||
{
|
||||
String config=_startConfig;
|
||||
String config = _startConfig;
|
||||
if (config == null || config.length() == 0)
|
||||
{
|
||||
config = System.getProperty("START","org/eclipse/jetty/start/start.config");
|
||||
}
|
||||
|
||||
|
||||
Config.debug("config=" + config);
|
||||
|
||||
// Look up config as resource first.
|
||||
|
@ -991,11 +978,10 @@ public class Main
|
|||
{
|
||||
cfgstream = new FileInputStream(config);
|
||||
}
|
||||
|
||||
|
||||
return cfgstream;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Stop a running jetty instance.
|
||||
*/
|
||||
|
@ -1038,7 +1024,6 @@ public class Main
|
|||
usageExit(e,ERR_UNKNOWN);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void usageExit(Throwable t, int exit)
|
||||
{
|
||||
|
@ -1048,6 +1033,7 @@ public class Main
|
|||
System.err.println(" java -jar start.jar --help # for more information");
|
||||
System.exit(exit);
|
||||
}
|
||||
|
||||
static void usageExit(int exit)
|
||||
{
|
||||
System.err.println();
|
||||
|
@ -1055,4 +1041,53 @@ public class Main
|
|||
System.err.println(" java -jar start.jar --help # for more information");
|
||||
System.exit(exit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a start.ini format file into an argument list.
|
||||
*/
|
||||
static List<String> loadStartIni(File ini)
|
||||
{
|
||||
File startIniFile = ini;
|
||||
if (!startIniFile.exists())
|
||||
{
|
||||
if (ini != null)
|
||||
{
|
||||
System.err.println("Warning - can't find ini file: " + ini);
|
||||
}
|
||||
// No start.ini found, skip load.
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
List<String> args = new ArrayList<String>();
|
||||
|
||||
FileReader reader = null;
|
||||
BufferedReader buf = null;
|
||||
try
|
||||
{
|
||||
reader = new FileReader(ini);
|
||||
buf = new BufferedReader(reader);
|
||||
|
||||
String arg;
|
||||
while ((arg = buf.readLine()) != null)
|
||||
{
|
||||
arg = arg.trim();
|
||||
if (arg.length() == 0 || arg.startsWith("#"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
args.add(arg);
|
||||
}
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
usageExit(e,ERR_UNKNOWN);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Main.close(buf);
|
||||
Main.close(reader);
|
||||
}
|
||||
|
||||
return args;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ Command Line Options:
|
|||
when the start.ini includes -X or -D arguments.
|
||||
|
||||
--exec Run the generated command line (see --dry-run) in
|
||||
a sub processes. This can be used when start.ini
|
||||
a sub process. This can be used when start.ini
|
||||
contains -X or -D arguments, but creates an extra
|
||||
JVM instance.
|
||||
|
||||
|
@ -36,8 +36,10 @@ Command Line Options:
|
|||
|
||||
--ini=<file> Load command line arguments from a file. If
|
||||
no --ini options are specified, then the
|
||||
start.ini file will be read if it exists.
|
||||
A --ini option with no file indicates that
|
||||
start.ini file will be read if it exists in
|
||||
jetty.home. If specified jetty.home/start.ini
|
||||
and additional .ini files in jetty.home/start.d/
|
||||
will NOT be read. A --ini option with no file indicates that
|
||||
start.ini should not be read.
|
||||
|
||||
--pre=<file> Specify a configuration file that is to be processed
|
||||
|
@ -116,8 +118,11 @@ Available Configurations:
|
|||
Defaults:
|
||||
A start.ini file may be used to specify default arguments to start.jar,
|
||||
which are used if no command line arguments are provided and override
|
||||
the defaults in the start.config file. If --ini options are provided on
|
||||
the command line, then start.ini will no be read. The current start.ini
|
||||
arguments are:
|
||||
the defaults in the start.config file. If the directory jetty.home/start.d
|
||||
exists, then multiple *.ini files will be read from that directory in
|
||||
alphabetical order. If --ini options are provided on the command line,
|
||||
then start.ini and start.d will NOT be read.
|
||||
|
||||
The current start.ini arguments are:
|
||||
|
||||
@STARTINI@
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
// ========================================================================
|
||||
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
|
||||
// ------------------------------------------------------------------------
|
||||
// All rights reserved. This program and the accompanying materials
|
||||
// are made available under the terms of the Eclipse Public License v1.0
|
||||
// and Apache License v2.0 which accompanies this distribution.
|
||||
// The Eclipse Public License is available at
|
||||
// http://www.eclipse.org/legal/epl-v10.html
|
||||
// The Apache License v2.0 is available at
|
||||
// http://www.opensource.org/licenses/apache2.0.php
|
||||
// You may elect to redistribute this code under either of these licenses.
|
||||
// ========================================================================
|
||||
|
||||
package org.eclipse.jetty.start;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
*/
|
||||
public class MainTest
|
||||
{
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* @throws java.lang.Exception
|
||||
*/
|
||||
@Before
|
||||
public void setUp() throws Exception
|
||||
{
|
||||
System.setProperty("jetty.home",this.getClass().getResource("/jetty.home").getFile());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.eclipse.jetty.start.StartIniParser#loadStartIni(java.lang.String)}.
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void testLoadStartIni() throws IOException
|
||||
{
|
||||
URL startIni = this.getClass().getResource("/jetty.home/");
|
||||
System.setProperty("jetty.home",startIni.getFile());
|
||||
Main main = new Main();
|
||||
List<String> args = main.parseStartIniFiles();
|
||||
assertEquals("Expected 5 uncommented lines in start.ini",9,args.size());
|
||||
assertEquals("First uncommented line in start.ini doesn't match expected result","OPTIONS=Server,jsp,resources,websocket,ext",args.get(0));
|
||||
assertEquals("Last uncommented line in start.ini doesn't match expected result","etc/jetty-testrealm.xml",args.get(8));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExpandCommandLine() throws Exception
|
||||
{
|
||||
Main main = new Main();
|
||||
List<String> args = main.expandCommandLine(new String[]{});
|
||||
assertEquals("start.ini OPTIONS","OPTIONS=Server,jsp,resources,websocket,ext",args.get(0));
|
||||
assertEquals("start.d/jmx OPTIONS","OPTIONS=jmx",args.get(5));
|
||||
assertEquals("start.d/jmx XML","--pre=etc/jetty-jmx.xml",args.get(6));
|
||||
assertEquals("start.d/websocket OPTIONS","OPTIONS=websocket",args.get(7));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProcessCommandLine() throws Exception
|
||||
{
|
||||
Main main = new Main();
|
||||
List<String> args = main.expandCommandLine(new String[]{});
|
||||
List<String> xmls = main.processCommandLine(args);
|
||||
|
||||
assertEquals("jmx --pre","etc/jetty-jmx.xml",xmls.get(0));
|
||||
assertEquals("start.ini","etc/jetty.xml",xmls.get(1));
|
||||
assertEquals("start.d","etc/jetty-testrealm.xml",xmls.get(5));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
#===========================================================
|
||||
# Additional Jetty start.jar arguments
|
||||
# Each line of this file is prepended to the command line
|
||||
# arguments # of a call to:
|
||||
# java -jar start.jar [arg...]
|
||||
#===========================================================
|
||||
|
||||
|
||||
|
||||
#===========================================================
|
||||
#-----------------------------------------------------------
|
||||
OPTIONS=jmx
|
||||
#-----------------------------------------------------------
|
||||
|
||||
|
||||
#===========================================================
|
||||
# Configuration files.
|
||||
# For a full list of available configuration files do
|
||||
# java -jar start.jar --help
|
||||
#-----------------------------------------------------------
|
||||
--pre=etc/jetty-jmx.xml
|
||||
#===========================================================
|
|
@ -0,0 +1,13 @@
|
|||
#===========================================================
|
||||
# Additional Jetty start.jar arguments
|
||||
# Each line of this file is prepended to the command line
|
||||
# arguments # of a call to:
|
||||
# java -jar start.jar [arg...]
|
||||
#===========================================================
|
||||
|
||||
|
||||
|
||||
#===========================================================
|
||||
#-----------------------------------------------------------
|
||||
OPTIONS=websocket
|
||||
#-----------------------------------------------------------
|
|
@ -0,0 +1 @@
|
|||
etc/jetty-testrealm.xml
|
|
@ -0,0 +1,65 @@
|
|||
#===========================================================
|
||||
# Jetty start.jar arguments
|
||||
# Each line of this file is prepended to the command line
|
||||
# arguments # of a call to:
|
||||
# java -jar start.jar [arg...]
|
||||
#===========================================================
|
||||
|
||||
|
||||
|
||||
#===========================================================
|
||||
# If the arguements in this file include JVM arguments
|
||||
# (eg -Xmx512m) or JVM System properties (eg com.sun.???),
|
||||
# then these will not take affect unless the --exec
|
||||
# parameter is included or if the output from --dry-run
|
||||
# is executed like:
|
||||
# eval $(java -jar start.jar --dry-run)
|
||||
#
|
||||
# Below are some recommended options for Sun's JRE
|
||||
#-----------------------------------------------------------
|
||||
# --exec
|
||||
# -Dorg.apache.jasper.compiler.disablejsr199=true
|
||||
# -Dcom.sun.management.jmxremote
|
||||
# -Dorg.eclipse.jetty.util.log.IGNORED=true
|
||||
# -Dorg.eclipse.jetty.util.log.stderr.DEBUG=true
|
||||
# -Dorg.eclipse.jetty.util.log.stderr.SOURCE=true
|
||||
# -Xmx2000m
|
||||
# -Xmn512m
|
||||
# -verbose:gc
|
||||
# -XX:+PrintGCDateStamps
|
||||
# -XX:+PrintGCTimeStamps
|
||||
# -XX:+PrintGCDetails
|
||||
# -XX:+PrintTenuringDistribution
|
||||
# -XX:+PrintCommandLineFlags
|
||||
# -XX:+DisableExplicitGC
|
||||
# -XX:+UseConcMarkSweepGC
|
||||
# -XX:ParallelCMSThreads=2
|
||||
# -XX:+CMSClassUnloadingEnabled
|
||||
# -XX:+UseCMSCompactAtFullCollection
|
||||
# -XX:CMSInitiatingOccupancyFraction=80
|
||||
#-----------------------------------------------------------
|
||||
|
||||
|
||||
#===========================================================
|
||||
# Start classpath OPTIONS.
|
||||
# These control what classes are on the classpath
|
||||
# for a full listing do
|
||||
# java -jar start.jar --list-options
|
||||
#-----------------------------------------------------------
|
||||
OPTIONS=Server,jsp,resources,websocket,ext
|
||||
#-----------------------------------------------------------
|
||||
|
||||
|
||||
#===========================================================
|
||||
# Configuration files.
|
||||
# For a full list of available configuration files do
|
||||
# java -jar start.jar --help
|
||||
#-----------------------------------------------------------
|
||||
etc/jetty.xml
|
||||
# etc/jetty-ssl.xml
|
||||
# etc/jetty-requestlog.xml
|
||||
etc/jetty-deploy.xml
|
||||
#etc/jetty-overlay.xml
|
||||
etc/jetty-webapps.xml
|
||||
etc/jetty-contexts.xml
|
||||
#===========================================================
|
|
@ -16,6 +16,7 @@ package org.eclipse.jetty.util;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.StringWriter;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
@ -78,13 +79,13 @@ public class UrlEncoded extends MultiMap implements Cloneable
|
|||
/* ----------------------------------------------------------------- */
|
||||
public void decode(String query)
|
||||
{
|
||||
decodeTo(query,this,ENCODING);
|
||||
decodeTo(query,this,ENCODING,-1);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- */
|
||||
public void decode(String query,String charset)
|
||||
{
|
||||
decodeTo(query,this,charset);
|
||||
decodeTo(query,this,charset,-1);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
|
@ -177,6 +178,15 @@ public class UrlEncoded extends MultiMap implements Cloneable
|
|||
* @param content the string containing the encoded parameters
|
||||
*/
|
||||
public static void decodeTo(String content, MultiMap map, String charset)
|
||||
{
|
||||
decodeTo(content,map,charset,-1);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/** Decoded parameters to Map.
|
||||
* @param content the string containing the encoded parameters
|
||||
*/
|
||||
public static void decodeTo(String content, MultiMap map, String charset, int maxKeys)
|
||||
{
|
||||
if (charset==null)
|
||||
charset=ENCODING;
|
||||
|
@ -208,6 +218,11 @@ public class UrlEncoded extends MultiMap implements Cloneable
|
|||
}
|
||||
key = null;
|
||||
value=null;
|
||||
if (maxKeys>0 && map.size()>maxKeys)
|
||||
{
|
||||
LOG.warn("maxFormKeys limit exceeded keys>{}",maxKeys);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case '=':
|
||||
if (key!=null)
|
||||
|
@ -343,9 +358,10 @@ public class UrlEncoded extends MultiMap implements Cloneable
|
|||
/** Decoded parameters to Map.
|
||||
* @param in InputSteam to read
|
||||
* @param map MultiMap to add parameters to
|
||||
* @param maxLength maximum length of content to read 0r -1 for no limit
|
||||
* @param maxLength maximum length of content to read or -1 for no limit
|
||||
* @param maxLength maximum number of keys to read or -1 for no limit
|
||||
*/
|
||||
public static void decode88591To(InputStream in, MultiMap map, int maxLength)
|
||||
public static void decode88591To(InputStream in, MultiMap map, int maxLength, int maxKeys)
|
||||
throws IOException
|
||||
{
|
||||
synchronized(map)
|
||||
|
@ -375,6 +391,11 @@ public class UrlEncoded extends MultiMap implements Cloneable
|
|||
}
|
||||
key = null;
|
||||
value=null;
|
||||
if (maxKeys>0 && map.size()>maxKeys)
|
||||
{
|
||||
LOG.warn("maxFormKeys limit exceeded keys>{}",maxKeys);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case '=':
|
||||
|
@ -423,9 +444,10 @@ public class UrlEncoded extends MultiMap implements Cloneable
|
|||
/** Decoded parameters to Map.
|
||||
* @param in InputSteam to read
|
||||
* @param map MultiMap to add parameters to
|
||||
* @param maxLength maximum length of content to read 0r -1 for no limit
|
||||
* @param maxLength maximum length of content to read or -1 for no limit
|
||||
* @param maxLength maximum number of keys to read or -1 for no limit
|
||||
*/
|
||||
public static void decodeUtf8To(InputStream in, MultiMap map, int maxLength)
|
||||
public static void decodeUtf8To(InputStream in, MultiMap map, int maxLength, int maxKeys)
|
||||
throws IOException
|
||||
{
|
||||
synchronized(map)
|
||||
|
@ -455,6 +477,11 @@ public class UrlEncoded extends MultiMap implements Cloneable
|
|||
}
|
||||
key = null;
|
||||
value=null;
|
||||
if (maxKeys>0 && map.size()>maxKeys)
|
||||
{
|
||||
LOG.warn("maxFormKeys limit exceeded keys>{}",maxKeys);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case '=':
|
||||
|
@ -500,25 +527,20 @@ public class UrlEncoded extends MultiMap implements Cloneable
|
|||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
public static void decodeUtf16To(InputStream in, MultiMap map, int maxLength) throws IOException
|
||||
public static void decodeUtf16To(InputStream in, MultiMap map, int maxLength, int maxKeys) throws IOException
|
||||
{
|
||||
InputStreamReader input = new InputStreamReader(in,StringUtil.__UTF16);
|
||||
StringBuffer buf = new StringBuffer();
|
||||
|
||||
int c;
|
||||
int length=0;
|
||||
if (maxLength<0)
|
||||
maxLength=Integer.MAX_VALUE;
|
||||
while ((c=input.read())>0 && length++<maxLength)
|
||||
buf.append((char)c);
|
||||
decodeTo(buf.toString(),map,ENCODING);
|
||||
StringWriter buf = new StringWriter(8192);
|
||||
IO.copy(input,buf,maxLength);
|
||||
|
||||
decodeTo(buf.getBuffer().toString(),map,ENCODING,maxKeys);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
/** Decoded parameters to Map.
|
||||
* @param in the stream containing the encoded parameters
|
||||
*/
|
||||
public static void decodeTo(InputStream in, MultiMap map, String charset, int maxLength)
|
||||
public static void decodeTo(InputStream in, MultiMap map, String charset, int maxLength, int maxKeys)
|
||||
throws IOException
|
||||
{
|
||||
//no charset present, use the configured default
|
||||
|
@ -527,22 +549,21 @@ public class UrlEncoded extends MultiMap implements Cloneable
|
|||
charset=ENCODING;
|
||||
}
|
||||
|
||||
|
||||
if (StringUtil.__UTF8.equalsIgnoreCase(charset))
|
||||
{
|
||||
decodeUtf8To(in,map,maxLength);
|
||||
decodeUtf8To(in,map,maxLength,maxKeys);
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringUtil.__ISO_8859_1.equals(charset))
|
||||
{
|
||||
decode88591To(in,map,maxLength);
|
||||
decode88591To(in,map,maxLength,maxKeys);
|
||||
return;
|
||||
}
|
||||
|
||||
if (StringUtil.__UTF16.equalsIgnoreCase(charset)) // Should be all 2 byte encodings
|
||||
{
|
||||
decodeUtf16To(in,map,maxLength);
|
||||
decodeUtf16To(in,map,maxLength,maxKeys);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -12,92 +12,224 @@ import org.eclipse.jetty.util.log.Log;
|
|||
import org.eclipse.jetty.util.log.Logger;
|
||||
|
||||
/**
|
||||
* An AggregateLifeCycle is an AbstractLifeCycle with a collection of dependent beans.
|
||||
* An AggregateLifeCycle is an {@link LifeCycle} implementation for a collection of contained beans.
|
||||
* <p>
|
||||
* Beans can be added the AggregateLifeCycle either as managed beans or as unmanaged beans. A managed bean is started, stopped and destroyed with the aggregate.
|
||||
* An umanaged bean is associated with the aggregate for the purposes of {@link #dump()}, but it's lifecycle must be managed externally.
|
||||
* <p>
|
||||
* When a bean is added, if it is a {@link LifeCycle} and it is already started, then it is assumed to be an unmanaged bean.
|
||||
* Otherwise the methods {@link #addBean(LifeCycle, boolean)}, {@link #manage(LifeCycle)} and {@link #unmanage(LifeCycle)} can be used to
|
||||
* explicitly control the life cycle relationship.
|
||||
* <p>
|
||||
* If adding a bean that is shared between multiple {@link AggregateLifeCycle} instances, then it should be started before being added, so it is unmanged, or
|
||||
* the API must be used to explicitly set it as unmanaged.
|
||||
* <p>
|
||||
* Dependent beans are started and stopped with the {@link LifeCycle} and if they are destroyed if they are also {@link Destroyable}.
|
||||
*
|
||||
*/
|
||||
public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable, Dumpable
|
||||
{
|
||||
private static final Logger LOG = Log.getLogger(AggregateLifeCycle.class);
|
||||
private final List<Object> _dependentBeans=new CopyOnWriteArrayList<Object>();
|
||||
private final List<Bean> _beans=new CopyOnWriteArrayList<Bean>();
|
||||
private boolean _started=false;
|
||||
|
||||
public void destroy()
|
||||
private class Bean
|
||||
{
|
||||
for (Object o : _dependentBeans)
|
||||
Bean(Object b)
|
||||
{
|
||||
if (o instanceof Destroyable)
|
||||
{
|
||||
((Destroyable)o).destroy();
|
||||
}
|
||||
_bean=b;
|
||||
}
|
||||
_dependentBeans.clear();
|
||||
final Object _bean;
|
||||
volatile boolean _managed=true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Start the managed lifecycle beans in the order they were added.
|
||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
|
||||
*/
|
||||
@Override
|
||||
protected void doStart() throws Exception
|
||||
{
|
||||
for (Object o:_dependentBeans)
|
||||
for (Bean b:_beans)
|
||||
{
|
||||
if (o instanceof LifeCycle)
|
||||
((LifeCycle)o).start();
|
||||
if (b._managed && b._bean instanceof LifeCycle)
|
||||
{
|
||||
LifeCycle l=(LifeCycle)b._bean;
|
||||
if (!l.isRunning())
|
||||
l.start();
|
||||
}
|
||||
}
|
||||
// indicate that we are started, so that addBean will start other beans added.
|
||||
_started=true;
|
||||
super.doStart();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Stop the joined lifecycle beans in the reverse order they were added.
|
||||
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
|
||||
*/
|
||||
@Override
|
||||
protected void doStop() throws Exception
|
||||
{
|
||||
_started=false;
|
||||
super.doStop();
|
||||
List<Object> reverse = new ArrayList<Object>(_dependentBeans);
|
||||
List<Bean> reverse = new ArrayList<Bean>(_beans);
|
||||
Collections.reverse(reverse);
|
||||
for (Object o:reverse)
|
||||
for (Bean b:reverse)
|
||||
{
|
||||
if (o instanceof LifeCycle)
|
||||
((LifeCycle)o).stop();
|
||||
if (b._managed && b._bean instanceof LifeCycle)
|
||||
{
|
||||
LifeCycle l=(LifeCycle)b._bean;
|
||||
if (l.isRunning())
|
||||
l.stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Destroy the joined Destroyable beans in the reverse order they were added.
|
||||
* @see org.eclipse.jetty.util.component.Destroyable#destroy()
|
||||
*/
|
||||
public void destroy()
|
||||
{
|
||||
List<Bean> reverse = new ArrayList<Bean>(_beans);
|
||||
Collections.reverse(reverse);
|
||||
for (Bean b:reverse)
|
||||
{
|
||||
if (b._bean instanceof Destroyable && b._managed)
|
||||
{
|
||||
Destroyable d=(Destroyable)b._bean;
|
||||
d.destroy();
|
||||
}
|
||||
}
|
||||
_beans.clear();
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Is the bean contained in the aggregate.
|
||||
* @param bean
|
||||
* @return True if the aggregate contains the bean
|
||||
*/
|
||||
public boolean contains(Object bean)
|
||||
{
|
||||
for (Bean b:_beans)
|
||||
if (b._bean==bean)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Is the bean joined to the aggregate.
|
||||
* @param bean
|
||||
* @return True if the aggregate contains the bean and it is joined
|
||||
*/
|
||||
public boolean isManaged(Object bean)
|
||||
{
|
||||
for (Bean b:_beans)
|
||||
if (b._bean==bean)
|
||||
return b._managed;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Add an associated bean.
|
||||
* The bean will be added to this LifeCycle and if it is also a
|
||||
* {@link LifeCycle} instance, it will be
|
||||
* started/stopped. Any beans that are also
|
||||
* {@link Destroyable}, will be destroyed with the server.
|
||||
* If the bean is a {@link LifeCycle}, then it will be managed if it is not
|
||||
* already started and umanaged if it is already started. The {@link #addBean(Object, boolean)}
|
||||
* method should be used if this is not correct, or the {@link #manage(Object)} and {@link #unmanage(Object)}
|
||||
* methods may be used after an add to change the status.
|
||||
* @param o the bean object to add
|
||||
* @return true if the bean was added or false if it has already been added.
|
||||
*/
|
||||
public boolean addBean(Object o)
|
||||
{
|
||||
if (o == null)
|
||||
// beans are joined unless they are started lifecycles
|
||||
return addBean(o,!((o instanceof LifeCycle)&&((LifeCycle)o).isStarted()));
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Add an associated lifecycle.
|
||||
* @param o The lifecycle to add
|
||||
* @param managed True if the LifeCycle is to be joined, otherwise it will be disjoint.
|
||||
* @return
|
||||
*/
|
||||
public boolean addBean(Object o, boolean managed)
|
||||
{
|
||||
if (contains(o))
|
||||
return false;
|
||||
boolean added=false;
|
||||
if (!_dependentBeans.contains(o))
|
||||
{
|
||||
_dependentBeans.add(o);
|
||||
added=true;
|
||||
}
|
||||
|
||||
try
|
||||
Bean b = new Bean(o);
|
||||
b._managed=managed;
|
||||
_beans.add(b);
|
||||
|
||||
if (o instanceof LifeCycle)
|
||||
{
|
||||
if (isStarted() && o instanceof LifeCycle)
|
||||
((LifeCycle)o).start();
|
||||
LifeCycle l=(LifeCycle)o;
|
||||
|
||||
// Start the bean if we are started
|
||||
if (managed && _started)
|
||||
{
|
||||
try
|
||||
{
|
||||
l.start();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new RuntimeException (e);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Manage a bean by this aggregate, so that it is started/stopped/destroyed with the
|
||||
* aggregate lifecycle.
|
||||
* @param bean The bean to manage (must already have been added).
|
||||
*/
|
||||
public void manage(Object bean)
|
||||
{
|
||||
for (Bean b :_beans)
|
||||
{
|
||||
throw new RuntimeException (e);
|
||||
if (b._bean==bean)
|
||||
{
|
||||
b._managed=true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
return added;
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/**
|
||||
* Unmanage a bean by this aggregate, so that it is not started/stopped/destroyed with the
|
||||
* aggregate lifecycle.
|
||||
* @param bean The bean to manage (must already have been added).
|
||||
*/
|
||||
public void unmanage(Object bean)
|
||||
{
|
||||
for (Bean b :_beans)
|
||||
{
|
||||
if (b._bean==bean)
|
||||
{
|
||||
b._managed=false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get dependent beans
|
||||
* @return List of beans.
|
||||
*/
|
||||
public Collection<Object> getBeans()
|
||||
{
|
||||
return _dependentBeans;
|
||||
return getBeans(Object.class);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -109,19 +241,17 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
|
|||
public <T> List<T> getBeans(Class<T> clazz)
|
||||
{
|
||||
ArrayList<T> beans = new ArrayList<T>();
|
||||
Iterator<?> iter = _dependentBeans.iterator();
|
||||
while (iter.hasNext())
|
||||
for (Bean b:_beans)
|
||||
{
|
||||
Object o = iter.next();
|
||||
if (clazz.isInstance(o))
|
||||
beans.add((T)o);
|
||||
if (clazz.isInstance(b._bean))
|
||||
beans.add((T)(b._bean));
|
||||
}
|
||||
return beans;
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Get dependent bean of a specific class.
|
||||
/** Get dependent beans of a specific class.
|
||||
* If more than one bean of the type exist, the first is returned.
|
||||
* @see #addBean(Object)
|
||||
* @param clazz
|
||||
|
@ -129,23 +259,13 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
|
|||
*/
|
||||
public <T> T getBean(Class<T> clazz)
|
||||
{
|
||||
Iterator<?> iter = _dependentBeans.iterator();
|
||||
T t=null;
|
||||
int count=0;
|
||||
while (iter.hasNext())
|
||||
for (Bean b:_beans)
|
||||
{
|
||||
Object o = iter.next();
|
||||
if (clazz.isInstance(o))
|
||||
{
|
||||
count++;
|
||||
if (t==null)
|
||||
t=(T)o;
|
||||
}
|
||||
if (clazz.isInstance(b._bean))
|
||||
return (T)b._bean;
|
||||
}
|
||||
if (count>1 && LOG.isDebugEnabled())
|
||||
LOG.debug("getBean({}) 1 of {}",clazz.getName(),count);
|
||||
|
||||
return t;
|
||||
return null;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -154,7 +274,7 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
|
|||
*/
|
||||
public void removeBeans ()
|
||||
{
|
||||
_dependentBeans.clear();
|
||||
_beans.clear();
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -163,9 +283,17 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
|
|||
*/
|
||||
public boolean removeBean (Object o)
|
||||
{
|
||||
if (o == null)
|
||||
return false;
|
||||
return _dependentBeans.remove(o);
|
||||
Iterator<Bean> i = _beans.iterator();
|
||||
while(i.hasNext())
|
||||
{
|
||||
Bean b=i.next();
|
||||
if (b._bean==o)
|
||||
{
|
||||
_beans.remove(b);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
@ -218,7 +346,32 @@ public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable
|
|||
public void dump(Appendable out,String indent) throws IOException
|
||||
{
|
||||
dumpThis(out);
|
||||
dump(out,indent,_dependentBeans);
|
||||
int size=_beans.size();
|
||||
if (size==0)
|
||||
return;
|
||||
int i=0;
|
||||
for (Bean b : _beans)
|
||||
{
|
||||
i++;
|
||||
|
||||
if (b._managed)
|
||||
{
|
||||
out.append(indent).append(" +- ");
|
||||
if (b._bean instanceof Dumpable)
|
||||
((Dumpable)b._bean).dump(out,indent+(i==size?" ":" | "));
|
||||
else
|
||||
out.append(String.valueOf(b._bean)).append("\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.append(indent).append(" +~ ");
|
||||
out.append(String.valueOf(b._bean)).append("\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (i!=size)
|
||||
out.append(indent).append(" |\n");
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
package org.eclipse.jetty.util.log;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
/** Abstract Logger.
|
||||
* Manages the atomic registration of the logger by name.
|
||||
*/
|
||||
public abstract class AbstractLogger implements Logger
|
||||
{
|
||||
public final Logger getLogger(String name)
|
||||
{
|
||||
if (isBlank(name))
|
||||
return this;
|
||||
|
||||
final String basename = getName();
|
||||
final String fullname = (isBlank(basename) || Log.getRootLogger()==this)?name:(basename + "." + name);
|
||||
|
||||
Logger logger = Log.getLoggers().get(fullname);
|
||||
if (logger == null)
|
||||
{
|
||||
Logger newlog = newLogger(fullname);
|
||||
|
||||
logger = Log.getMutableLoggers().putIfAbsent(fullname,newlog);
|
||||
if (logger == null)
|
||||
logger=newlog;
|
||||
}
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
|
||||
protected abstract Logger newLogger(String fullname);
|
||||
|
||||
/**
|
||||
* A more robust form of name blank test. Will return true for null names, and names that have only whitespace
|
||||
*
|
||||
* @param name
|
||||
* the name to test
|
||||
* @return true for null or blank name, false if any non-whitespace character is found.
|
||||
*/
|
||||
private static boolean isBlank(String name)
|
||||
{
|
||||
if (name == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
int size = name.length();
|
||||
char c;
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
c = name.charAt(i);
|
||||
if (!Character.isWhitespace(c))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -28,7 +28,7 @@ import java.util.logging.Level;
|
|||
* standard java.util.logging configuration</a>.
|
||||
* </p>
|
||||
*/
|
||||
public class JavaUtilLog implements Logger
|
||||
public class JavaUtilLog extends AbstractLogger
|
||||
{
|
||||
private Level configuredLevel;
|
||||
private java.util.logging.Logger _logger;
|
||||
|
@ -116,9 +116,12 @@ public class JavaUtilLog implements Logger
|
|||
_logger.log(Level.FINE, msg, thrown);
|
||||
}
|
||||
|
||||
public Logger getLogger(String name)
|
||||
/**
|
||||
* Create a Child Logger of this Logger.
|
||||
*/
|
||||
protected Logger newLogger(String fullname)
|
||||
{
|
||||
return new JavaUtilLog(name);
|
||||
return new JavaUtilLog(fullname);
|
||||
}
|
||||
|
||||
public void ignore(Throwable ignored)
|
||||
|
|
|
@ -19,8 +19,14 @@ import java.lang.reflect.Method;
|
|||
import java.net.URL;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import org.eclipse.jetty.util.IO;
|
||||
import org.eclipse.jetty.util.Loader;
|
||||
|
@ -59,6 +65,12 @@ public class Log
|
|||
*/
|
||||
public static boolean __ignored;
|
||||
|
||||
/**
|
||||
* Hold loggers only.
|
||||
*/
|
||||
private final static ConcurrentMap<String, Logger> __loggers = new ConcurrentHashMap<String, Logger>();
|
||||
|
||||
|
||||
static
|
||||
{
|
||||
/* Instantiate a default configuration properties (empty)
|
||||
|
@ -102,7 +114,10 @@ public class Log
|
|||
while (systemKeyEnum.hasMoreElements())
|
||||
{
|
||||
String key = systemKeyEnum.nextElement();
|
||||
__props.setProperty(key,System.getProperty(key));
|
||||
String val = System.getProperty(key);
|
||||
//protect against application code insertion of non-String values (returned as null)
|
||||
if (val != null)
|
||||
__props.setProperty(key,val);
|
||||
}
|
||||
|
||||
/* Now use the configuration properties to configure the Log statics
|
||||
|
@ -415,6 +430,28 @@ public class Log
|
|||
if (!initialized())
|
||||
return null;
|
||||
|
||||
return name == null ? LOG : LOG.getLogger(name);
|
||||
if(name==null)
|
||||
return LOG;
|
||||
|
||||
Logger logger = __loggers.get(name);
|
||||
if(logger==null)
|
||||
logger = LOG.getLogger(name);
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
static ConcurrentMap<String, Logger> getMutableLoggers()
|
||||
{
|
||||
return __loggers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a map of all configured {@link Logger} instances.
|
||||
*
|
||||
* @return a map of all configured {@link Logger} instances
|
||||
*/
|
||||
public static Map<String, Logger> getLoggers()
|
||||
{
|
||||
return Collections.unmodifiableMap(__loggers);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ import java.lang.reflect.Method;
|
|||
/**
|
||||
*
|
||||
*/
|
||||
public class LoggerLog implements Logger
|
||||
public class LoggerLog extends AbstractLogger
|
||||
{
|
||||
private final Object _logger;
|
||||
private final Method _debugMT;
|
||||
|
@ -189,11 +189,14 @@ public class LoggerLog implements Logger
|
|||
}
|
||||
}
|
||||
|
||||
public Logger getLogger(String name)
|
||||
/**
|
||||
* Create a Child Logger of this Logger.
|
||||
*/
|
||||
protected Logger newLogger(String fullname)
|
||||
{
|
||||
try
|
||||
{
|
||||
Object logger=_getLoggerN.invoke(_logger, name);
|
||||
Object logger=_getLoggerN.invoke(_logger, fullname);
|
||||
return new LoggerLog(logger);
|
||||
}
|
||||
catch (Exception e)
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue