Merge branch 'jetty-8' into release-8

This commit is contained in:
Jesse McConnell 2012-01-13 09:19:09 -06:00
commit 574851a830
144 changed files with 5370 additions and 2923 deletions

View File

@ -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.

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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()

View File

@ -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
{
}
}

View File

@ -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();
}
}
}

View File

@ -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();

View File

@ -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);
}
}

View File

@ -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));

View File

@ -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

View File

@ -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())

View File

@ -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

View File

@ -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"

View File

@ -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>

View File

@ -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>

View File

@ -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();
}

View File

@ -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;
}
}

View File

@ -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=='/')

View File

@ -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());
}
/**

View File

@ -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>

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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())

View File

@ -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);
}
}

View File

@ -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;

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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;
}
/**

View File

@ -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)

View File

@ -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>

View File

@ -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);
}
}
/**

View File

@ -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);
}
}

View File

@ -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

View File

@ -1,3 +0,0 @@
Logger: Jetty Logging implementaton
debugEnabled: True if debug enabled
name: Logger name

View File

@ -1 +0,0 @@
StdErrLog: Log adapter that logs to stderr

View File

@ -66,7 +66,6 @@
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>${javax-mail-version}</version>
<exclusions>
<exclusion>
<groupId>javax.activation</groupId>

View File

@ -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

View File

@ -1,2 +1 @@
ThreadMonitor: Detect and report spinning and deadlocked threads

View File

@ -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;

View File

@ -68,7 +68,6 @@
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>${junit4-version}</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@ -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)

View File

@ -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>

View File

@ -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>

View File

@ -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",

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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>

View File

@ -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;

View File

@ -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;

View File

@ -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)
{

View File

@ -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)
{

View File

@ -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
{

View File

@ -115,7 +115,6 @@
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.8.5</version>
<scope>test</scope>
</dependency>
</dependencies>

View File

@ -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");
}
}

View File

@ -216,9 +216,6 @@ public class AsyncContinuation implements AsyncContext, Continuation
}
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see javax.servlet.ServletRequest#isSuspended()
*/
public boolean isSuspending()
{
synchronized(this)

View File

@ -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);
}

View File

@ -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();
}
}
}

View File

@ -467,7 +467,6 @@ public class Response implements HttpServletResponse
}
}
location=encodeRedirectURL(location);
resetBuffer();
setHeader(HttpHeaders.LOCATION,location);
setStatus(HttpServletResponse.SC_MOVED_TEMPORARILY);

View File

@ -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 '/'

View File

@ -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;

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
/* ------------------------------------------------------------- */

View File

@ -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

View File

@ -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);
}

View File

@ -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;

View File

@ -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));

View File

@ -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();
}

View File

@ -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);
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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;
}
}

View File

@ -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
{
}
}
}

View File

@ -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);

View File

@ -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");
}
}

View File

@ -3,4 +3,3 @@ name: RO:Name
displayName: RO:Display Name
className: RO:Class Name
initParameters: RO:Initial parameters

View File

@ -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)

View File

@ -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)
{

View File

@ -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
{

View File

@ -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)

View File

@ -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;
}
}

View File

@ -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@

View File

@ -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));
}
}

View File

@ -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
#===========================================================

View File

@ -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
#-----------------------------------------------------------

View File

@ -0,0 +1 @@
etc/jetty-testrealm.xml

View File

@ -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
#===========================================================

View File

@ -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;
}

View File

@ -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");
}
/* ------------------------------------------------------------ */

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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);
}
}

View File

@ -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