Merge remote-tracking branch 'origin/master' into servlet-3.1-api

This commit is contained in:
Jan Bartel 2013-05-06 14:46:28 +10:00
commit 8d0cf5e949
36 changed files with 803 additions and 363 deletions

View File

@ -1,4 +1,5 @@
language: java
script: mvn install
jdk:
- openjdk7
- oraclejdk7

View File

@ -40,6 +40,7 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
public static final int DEFAULT_MAX_CONTENT_LENGTH = 4096;
public static final Logger LOG = Log.getLogger(AuthenticationProtocolHandler.class);
private static final Pattern AUTHENTICATE_PATTERN = Pattern.compile("([^\\s]+)\\s+realm=\"([^\"]+)\"(.*)", Pattern.CASE_INSENSITIVE);
private static final String AUTHENTICATION_ATTRIBUTE = AuthenticationProtocolHandler.class.getName() + ".authentication";
private final HttpClient client;
private final int maxContentLength;
@ -90,6 +91,15 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
return;
}
HttpConversation conversation = client.getConversation(request.getConversationID(), false);
if (conversation.getAttribute(AUTHENTICATION_ATTRIBUTE) != null)
{
// We have already tried to authenticate, but we failed again
LOG.debug("Bad credentials for {}", request);
forwardSuccessComplete(request, response);
return;
}
HttpHeader header = getAuthenticateHeader();
List<Authentication.HeaderInfo> headerInfos = parseAuthenticateHeader(response, header);
if (headerInfos.isEmpty())
@ -118,7 +128,6 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
return;
}
HttpConversation conversation = client.getConversation(request.getConversationID(), false);
final Authentication.Result authnResult = authentication.authenticate(request, response, headerInfo, conversation);
LOG.debug("Authentication result {}", authnResult);
if (authnResult == null)
@ -127,6 +136,8 @@ public abstract class AuthenticationProtocolHandler implements ProtocolHandler
return;
}
conversation.setAttribute(AUTHENTICATION_ATTRIBUTE, true);
Request newRequest = client.copyRequest(request, request.getURI());
authnResult.apply(newRequest);
newRequest.onResponseSuccess(new Response.SuccessListener()

View File

@ -63,6 +63,7 @@ import org.eclipse.jetty.io.ssl.SslConnection;
import org.eclipse.jetty.util.Jetty;
import org.eclipse.jetty.util.Promise;
import org.eclipse.jetty.util.SocketAddressResolver;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -362,7 +363,7 @@ public class HttpClient extends ContainerLifeCycle
*/
public Request newRequest(String host, int port)
{
return newRequest(URI.create(address("http", host, port)));
return newRequest(address("http", host, port));
}
/**
@ -417,9 +418,11 @@ public class HttpClient extends ContainerLifeCycle
return newRequest;
}
private String address(String scheme, String host, int port)
protected String address(String scheme, String host, int port)
{
return scheme + "://" + host + ":" + port;
StringBuilder result = new StringBuilder();
URIUtil.appendSchemeHostPort(result, scheme, host, port);
return result.toString();
}
/**
@ -900,6 +903,13 @@ public class HttpClient extends ContainerLifeCycle
return encodingField;
}
protected String normalizeHost(String host)
{
if (host != null && host.matches("\\[.*\\]"))
return host.substring(1, host.length() - 1);
return host;
}
protected int normalizePort(String scheme, int port)
{
return port > 0 ? port : HttpScheme.HTTPS.is(scheme) ? 443 : 80;

View File

@ -18,14 +18,10 @@
package org.eclipse.jetty.client;
import java.io.UnsupportedEncodingException;
import java.net.HttpCookie;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
@ -35,17 +31,14 @@ import org.eclipse.jetty.client.api.Connection;
import org.eclipse.jetty.client.api.ContentProvider;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.util.StringContentProvider;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpHeaderValue;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.http.MimeTypes;
import org.eclipse.jetty.io.AbstractConnection;
import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
@ -166,45 +159,12 @@ public class HttpConnection extends AbstractConnection implements Connection
path = "/";
request.path(path);
}
if (destination.isProxied() && HttpMethod.CONNECT != request.getMethod())
if (destination.isProxied() && HttpMethod.CONNECT != method)
{
path = request.getURI().toString();
request.path(path);
}
Fields fields = request.getParams();
if (!fields.isEmpty())
{
StringBuilder params = new StringBuilder();
for (Iterator<Fields.Field> fieldIterator = fields.iterator(); fieldIterator.hasNext();)
{
Fields.Field field = fieldIterator.next();
String[] values = field.values();
for (int i = 0; i < values.length; ++i)
{
if (i > 0)
params.append("&");
params.append(field.name()).append("=");
params.append(urlEncode(values[i]));
}
if (fieldIterator.hasNext())
params.append("&");
}
// POST with no content, send parameters as body
if (method == HttpMethod.POST && request.getContent() == null)
{
request.header(HttpHeader.CONTENT_TYPE, MimeTypes.Type.FORM_ENCODED.asString());
request.content(new StringContentProvider(params.toString()));
}
else
{
path += "?";
path += params.toString();
request.path(path);
}
}
// If we are HTTP 1.1, add the Host header
if (version.getVersion() > 10)
{
@ -257,19 +217,6 @@ public class HttpConnection extends AbstractConnection implements Connection
}
}
private String urlEncode(String value)
{
String encoding = "UTF-8";
try
{
return URLEncoder.encode(value, encoding);
}
catch (UnsupportedEncodingException e)
{
throw new UnsupportedCharsetException(encoding);
}
}
public HttpExchange getExchange()
{
return exchange.get();

View File

@ -22,10 +22,12 @@ import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.UnsupportedCharsetException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@ -62,6 +64,7 @@ public class HttpRequest implements Request
private URI uri;
private String scheme;
private String path;
private String query;
private HttpMethod method;
private HttpVersion version;
private long idleTimeout;
@ -80,35 +83,15 @@ public class HttpRequest implements Request
this.client = client;
this.conversation = conversation;
scheme = uri.getScheme();
host = uri.getHost();
host = client.normalizeHost(uri.getHost());
port = client.normalizePort(scheme, uri.getPort());
path = uri.getRawPath();
String query = uri.getRawQuery();
if (query != null)
{
for (String nameValue : query.split("&"))
{
String[] parts = nameValue.split("=");
param(parts[0], parts.length < 2 ? "" : urlDecode(parts[1]));
}
}
query = uri.getRawQuery();
extractParams(query);
this.uri = buildURI();
followRedirects(client.isFollowRedirects());
}
private String urlDecode(String value)
{
String charset = "UTF-8";
try
{
return URLDecoder.decode(value, charset);
}
catch (UnsupportedEncodingException x)
{
throw new UnsupportedCharsetException(charset);
}
}
@Override
public long getConversationID()
{
@ -163,11 +146,25 @@ public class HttpRequest implements Request
@Override
public Request path(String path)
{
this.path = path;
URI uri = URI.create(path);
this.path = uri.getRawPath();
String query = uri.getRawQuery();
if (query != null)
{
this.query = query;
params.clear();
extractParams(query);
}
this.uri = buildURI();
return this;
}
@Override
public String getQuery()
{
return query;
}
@Override
public URI getURI()
{
@ -191,13 +188,14 @@ public class HttpRequest implements Request
public Request param(String name, String value)
{
params.add(name, value);
this.query = buildQuery();
return this;
}
@Override
public Fields getParams()
{
return params;
return new Fields(params, true);
}
@Override
@ -496,12 +494,73 @@ public class HttpRequest implements Request
return aborted;
}
private String buildQuery()
{
StringBuilder result = new StringBuilder();
for (Iterator<Fields.Field> iterator = params.iterator(); iterator.hasNext();)
{
Fields.Field field = iterator.next();
String[] values = field.values();
for (int i = 0; i < values.length; ++i)
{
if (i > 0)
result.append("&");
result.append(field.name()).append("=");
result.append(urlEncode(values[i]));
}
if (iterator.hasNext())
result.append("&");
}
return result.toString();
}
private String urlEncode(String value)
{
String encoding = "UTF-8";
try
{
return URLEncoder.encode(value, encoding);
}
catch (UnsupportedEncodingException e)
{
throw new UnsupportedCharsetException(encoding);
}
}
private void extractParams(String query)
{
if (query != null)
{
for (String nameValue : query.split("&"))
{
String[] parts = nameValue.split("=");
param(parts[0], parts.length < 2 ? "" : urlDecode(parts[1]));
}
}
}
private String urlDecode(String value)
{
String charset = "UTF-8";
try
{
return URLDecoder.decode(value, charset);
}
catch (UnsupportedEncodingException x)
{
throw new UnsupportedCharsetException(charset);
}
}
private URI buildURI()
{
String path = getPath();
String query = getQuery();
if (query != null)
path += "?" + query;
URI result = URI.create(path);
if (!result.isAbsolute())
result = URI.create(getScheme() + "://" + getHost() + ":" + getPort() + path);
result = URI.create(client.address(getScheme(), getHost(), getPort()) + path);
return result;
}

View File

@ -172,7 +172,11 @@ public class HttpSender implements AsyncContentProvider.Listener
{
ContentProvider requestContent = request.getContent();
long contentLength = requestContent == null ? -1 : requestContent.getLength();
requestInfo = new HttpGenerator.RequestInfo(request.getVersion(), request.getHeaders(), contentLength, request.getMethod().asString(), request.getPath());
String path = request.getPath();
String query = request.getQuery();
if (query != null)
path += "?" + query;
requestInfo = new HttpGenerator.RequestInfo(request.getVersion(), request.getHeaders(), contentLength, request.getMethod().asString(), path);
break;
}
case NEED_HEADER:

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.client.api;
import java.io.IOException;
import java.net.URI;
import java.net.URLEncoder;
import java.nio.ByteBuffer;
import java.nio.file.Path;
import java.util.EventListener;
@ -86,18 +87,33 @@ public interface Request
Request method(HttpMethod method);
/**
* @return the path of this request, such as "/"
* @return the path of this request, such as "/" or "/path" - without the query
* @see #getQuery()
*/
String getPath();
/**
* @param path the path of this request, such as "/"
* Specifies the path - and possibly the query - of this request.
* If the query part is specified, parameter values must be properly
* {@link URLEncoder#encode(String, String) UTF-8 URL encoded}.
* For example, if the parameter value is the euro symbol &euro; then the
* query string must be "param=%E2%82%AC".
* For transparent encoding of parameter values, use {@link #param(String, String)}.
*
* @param path the path of this request, such as "/" or "/path?param=1"
* @return this request object
*/
Request path(String path);
/**
* @return the full URI of this request such as "http://host:port/path"
* @return the query string of this request such as "param=1"
* @see #getPath()
* @see #getParams()
*/
String getQuery();
/**
* @return the full URI of this request such as "http://host:port/path?param=1"
*/
URI getURI();
@ -118,6 +134,9 @@ public interface Request
Fields getParams();
/**
* Adds a query parameter with the given name and value.
* The value is {@link URLEncoder#encode(String, String) UTF-8 URL encoded}.
*
* @param name the name of the query parameter
* @param value the value of the query parameter
* @return this request object

View File

@ -20,7 +20,6 @@ package org.eclipse.jetty.client;
import java.io.IOException;
import java.net.Socket;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@ -94,8 +93,6 @@ public class ExternalSiteTest
{
Assert.assertTrue(result.isSucceeded());
Assert.assertEquals(200, result.getResponse().getStatus());
URI uri = result.getRequest().getURI();
Assert.assertTrue(uri.getPort() > 0);
latch2.countDown();
}
});

View File

@ -303,4 +303,20 @@ public class HttpClientAuthenticationTest extends AbstractHttpClientServerTest
Assert.assertEquals(401, response.getStatus());
Assert.assertTrue(requests.get().await(5, TimeUnit.SECONDS));
}
@Test
public void test_BasicAuthentication_WithWrongPassword() throws Exception
{
startBasic(new EmptyServerHandler());
AuthenticationStore authenticationStore = client.getAuthenticationStore();
URI uri = URI.create(scheme + "://localhost:" + connector.getLocalPort());
BasicAuthentication authentication = new BasicAuthentication(uri, realm, "basic", "wrong");
authenticationStore.addAuthentication(authentication);
Request request = client.newRequest("localhost", connector.getLocalPort()).scheme(scheme).path("/secure");
ContentResponse response = request.timeout(555, TimeUnit.SECONDS).send();
Assert.assertNotNull(response);
Assert.assertEquals(401, response.getStatus());
}
}

View File

@ -0,0 +1,241 @@
//
// ========================================================================
// Copyright (c) 1995-2013 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.URLEncoder;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.client.api.ContentResponse;
import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.util.Fields;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.junit.Assert;
import org.junit.Test;
public class HttpClientURITest extends AbstractHttpClientServerTest
{
public HttpClientURITest(SslContextFactory sslContextFactory)
{
super(sslContextFactory);
}
@Test
public void testIPv6Host() throws Exception
{
start(new EmptyServerHandler());
String host = "::1";
Request request = client.newRequest(host, connector.getLocalPort())
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS);
Assert.assertEquals(host, request.getHost());
StringBuilder uri = new StringBuilder();
URIUtil.appendSchemeHostPort(uri, scheme, host, connector.getLocalPort());
Assert.assertEquals(uri.toString(), request.getURI().toString());
Assert.assertEquals(HttpStatus.OK_200, request.send().getStatus());
}
@Test
public void testPath() throws Exception
{
final String path = "/path";
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
Assert.assertEquals(path, request.getRequestURI());
}
});
Request request = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS)
.path(path);
Assert.assertEquals(path, request.getPath());
Assert.assertNull(request.getQuery());
Fields params = request.getParams();
Assert.assertEquals(0, params.size());
Assert.assertTrue(request.getURI().toString().endsWith(path));
ContentResponse response = request.send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
@Test
public void testPathWithQuery() throws Exception
{
String name = "a";
String value = "1";
final String query = name + "=" + value;
final String path = "/path";
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
Assert.assertEquals(path, request.getRequestURI());
Assert.assertEquals(query, request.getQueryString());
}
});
Request request = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS)
.path(path + "?" + query);
Assert.assertEquals(path, request.getPath());
Assert.assertEquals(query, request.getQuery());
Fields params = request.getParams();
Assert.assertEquals(1, params.size());
Assert.assertEquals(value, params.get(name).value());
ContentResponse response = request.send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
@Test
public void testPathWithParam() throws Exception
{
String name = "a";
String value = "1";
final String query = name + "=" + value;
final String path = "/path";
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
Assert.assertEquals(path, request.getRequestURI());
Assert.assertEquals(query, request.getQueryString());
}
});
Request request = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS)
.path(path)
.param(name, value);
Assert.assertEquals(path, request.getPath());
Assert.assertEquals(query, request.getQuery());
Fields params = request.getParams();
Assert.assertEquals(1, params.size());
Assert.assertEquals(value, params.get(name).value());
ContentResponse response = request.send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
@Test
public void testPathWithQueryAndParam() throws Exception
{
String name1 = "a";
String value1 = "1";
String name2 = "b";
String value2 = "2";
final String query = name1 + "=" + value1 + "&" + name2 + "=" + value2;
final String path = "/path";
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
Assert.assertEquals(path, request.getRequestURI());
Assert.assertEquals(query, request.getQueryString());
}
});
Request request = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS)
.path(path + "?" + name1 + "=" + value1)
.param(name2, value2);
Assert.assertEquals(path, request.getPath());
Assert.assertEquals(query, request.getQuery());
Fields params = request.getParams();
Assert.assertEquals(2, params.size());
Assert.assertEquals(value1, params.get(name1).value());
Assert.assertEquals(value2, params.get(name2).value());
ContentResponse response = request.send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
@Test
public void testPathWithQueryAndParamValueEncoded() throws Exception
{
final String name1 = "a";
final String value1 = "\u20AC";
final String encodedValue1 = URLEncoder.encode(value1, "UTF-8");
final String name2 = "b";
final String value2 = "\u00A5";
String encodedValue2 = URLEncoder.encode(value2, "UTF-8");
final String query = name1 + "=" + encodedValue1 + "&" + name2 + "=" + encodedValue2;
final String path = "/path";
start(new AbstractHandler()
{
@Override
public void handle(String target, org.eclipse.jetty.server.Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
{
baseRequest.setHandled(true);
Assert.assertEquals(path, request.getRequestURI());
Assert.assertEquals(query, request.getQueryString());
Assert.assertEquals(value1, request.getParameter(name1));
Assert.assertEquals(value2, request.getParameter(name2));
}
});
Request request = client.newRequest("localhost", connector.getLocalPort())
.scheme(scheme)
.timeout(5, TimeUnit.SECONDS)
.path(path + "?" + name1 + "=" + encodedValue1)
.param(name2, value2);
Assert.assertEquals(path, request.getPath());
Assert.assertEquals(query, request.getQuery());
Fields params = request.getParams();
Assert.assertEquals(2, params.size());
Assert.assertEquals(value1, params.get(name1).value());
Assert.assertEquals(value2, params.get(name2).value());
ContentResponse response = request.send();
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
}
}

View File

@ -24,6 +24,8 @@ import java.util.Arrays;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@ -66,7 +68,10 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(0, activeConnections.size());
final CountDownLatch headersLatch = new CountDownLatch(1);
final CountDownLatch testLatch = new CountDownLatch(1);
final CountDownLatch successLatch = new CountDownLatch(3);
final AtomicBoolean failed = new AtomicBoolean(false);
client.newRequest(host, port)
.scheme(scheme)
.onRequestSuccess(new Request.SuccessListener()
@ -82,9 +87,15 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
@Override
public void onHeaders(Response response)
{
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(1, activeConnections.size());
headersLatch.countDown();
try
{
testLatch.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
})
.send(new Response.Listener.Empty()
@ -98,16 +109,21 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
@Override
public void onComplete(Result result)
{
Assert.assertFalse(result.isFailed());
failed.set(result.isFailed());
successLatch.countDown();
}
});
Assert.assertTrue(headersLatch.await(5, TimeUnit.SECONDS));
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(1, activeConnections.size());
testLatch.countDown();
Assert.assertTrue(successLatch.await(5, TimeUnit.SECONDS));
Assert.assertEquals(1, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
Assert.assertFalse(failed.get());
}
@Test
@ -127,6 +143,8 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
final CountDownLatch beginLatch = new CountDownLatch(1);
final CountDownLatch failureLatch = new CountDownLatch(2);
final AtomicBoolean failed = new AtomicBoolean(false);
client.newRequest(host, port).scheme(scheme).listener(new Request.Listener.Empty()
{
@Override
@ -146,9 +164,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
@Override
public void onComplete(Result result)
{
Assert.assertTrue(result.isFailed());
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
failed.set(result.isFailed());
failureLatch.countDown();
}
});
@ -158,6 +174,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
Assert.assertTrue(failed.get());
}
@Test
@ -176,6 +193,9 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(0, activeConnections.size());
final CountDownLatch successLatch = new CountDownLatch(3);
final AtomicBoolean failed = new AtomicBoolean(false);
final AtomicBoolean four_hundred = new AtomicBoolean(false);
client.newRequest(host, port)
.scheme(scheme)
.listener(new Request.Listener.Empty()
@ -198,16 +218,16 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
@Override
public void onSuccess(Response response)
{
Assert.assertEquals(400, response.getStatus());
// 400 response also come with a Connection: close,
// so the connection is closed and removed
four_hundred.set(response.getStatus()==400);
successLatch.countDown();
}
@Override
public void onComplete(Result result)
{
Assert.assertFalse(result.isFailed());
failed.set(result.isFailed());
successLatch.countDown();
}
});
@ -216,6 +236,8 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
Assert.assertFalse(failed.get());
Assert.assertTrue(four_hundred.get());
}
@Slow
@ -236,6 +258,8 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
final long delay = 1000;
final CountDownLatch successLatch = new CountDownLatch(3);
final AtomicBoolean failed = new AtomicBoolean(false);
final AtomicBoolean four_hundred = new AtomicBoolean(false);
client.newRequest(host, port)
.scheme(scheme)
.listener(new Request.Listener.Empty()
@ -271,16 +295,16 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
@Override
public void onSuccess(Response response)
{
Assert.assertEquals(400, response.getStatus());
// 400 response also come with a Connection: close,
// so the connection is closed and removed
four_hundred.set(response.getStatus()==400);
successLatch.countDown();
}
@Override
public void onComplete(Result result)
{
Assert.assertFalse(result.isFailed());
failed.set(result.isFailed());
successLatch.countDown();
}
});
@ -289,6 +313,8 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
Assert.assertFalse(failed.get());
Assert.assertTrue(four_hundred.get());
}
@Test
@ -309,6 +335,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
server.stop();
final CountDownLatch failureLatch = new CountDownLatch(2);
final AtomicBoolean failed = new AtomicBoolean(false);
client.newRequest(host, port)
.scheme(scheme)
.onRequestFailure(new Request.FailureListener()
@ -324,7 +351,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
@Override
public void onComplete(Result result)
{
Assert.assertTrue(result.isFailed());
failed.set(result.isFailed());
failureLatch.countDown();
}
});
@ -333,6 +360,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
Assert.assertTrue(failed.get());
}
@Test
@ -359,6 +387,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(0, activeConnections.size());
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean failed = new AtomicBoolean(false);
client.newRequest(host, port)
.scheme(scheme)
.send(new Response.Listener.Empty()
@ -366,9 +395,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
@Override
public void onComplete(Result result)
{
Assert.assertFalse(result.isFailed());
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
failed.set(result.isFailed());
latch.countDown();
}
});
@ -377,6 +404,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
Assert.assertFalse(failed.get());
}
@Test
@ -410,6 +438,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Log.getLogger(HttpConnection.class).info("Expecting java.lang.IllegalStateException: HttpParser{s=CLOSED,...");
final CountDownLatch latch = new CountDownLatch(1);
final AtomicBoolean failed = new AtomicBoolean(false);
ByteBuffer buffer = ByteBuffer.allocate(16 * 1024 * 1024);
Arrays.fill(buffer.array(),(byte)'x');
client.newRequest(host, port)
@ -420,8 +449,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
@Override
public void onComplete(Result result)
{
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
failed.set(result.isFailed());
latch.countDown();
}
});
@ -430,6 +458,7 @@ public class HttpConnectionLifecycleTest extends AbstractHttpClientServerTest
Assert.assertEquals(0, idleConnections.size());
Assert.assertEquals(0, activeConnections.size());
Assert.assertTrue(failed.get());
server.stop();
}
finally

View File

@ -44,6 +44,7 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
import org.eclipse.jetty.toolchain.test.PathAssert;
import org.eclipse.jetty.toolchain.test.TestingDir;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.xml.XmlConfiguration;
@ -290,9 +291,7 @@ public class XmlConfiguredJetty
public URI getServerURI() throws UnknownHostException
{
StringBuilder uri = new StringBuilder();
uri.append(getScheme()).append("://");
uri.append(InetAddress.getLocalHost().getHostAddress());
uri.append(":").append(getServerPort());
URIUtil.appendSchemeHostPort(uri, getScheme(), InetAddress.getLocalHost().getHostAddress(), getServerPort());
return URI.create(uri.toString());
}

View File

@ -22,13 +22,25 @@
# + A JVM option like: -Xmx2000m
# + A System Property like: -Dcom.sun.management.jmxremote
#
#-----------------------------------------------------------
#
# NOTE: The lines in this file may be uncommented to activate
# features. Alternately, the lines may be copied to a ini file
# in the start.d directory to enabled configuration without
# editing this file. See start.d/900-demo.ini for an example.
#
# Future releases will switch start.d style configuration for
# all features.
#===========================================================
#===========================================================
#===========================================================
# Configure JVM arguments.
# If JVM args are uncommented here then --exec is needed
# to start a new JVM from start.jar with the extra args
# If JVM args are include in an ini file then --exec is needed
# to start a new JVM from start.jar with the extra args.
# If you wish to avoid an extra JVM running, place JVM args
# on the normal command line and do not use --exec
#-----------------------------------------------------------
# --exec
# -Xmx2000m

View File

@ -95,7 +95,7 @@
<version>${exam.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.ops4j.pax.runner</groupId>
<artifactId>pax-runner-no-jcl</artifactId>
@ -141,12 +141,14 @@
<scope>test</scope>
</dependency>
<!-- For sane logging -->
<!--
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
-->
<!-- Orbit Servlet Deps -->
<dependency>
<groupId>javax.servlet</groupId>
@ -258,7 +260,7 @@
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.spdy</groupId>
<artifactId>spdy-core</artifactId>
@ -296,7 +298,7 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>

View File

@ -78,17 +78,21 @@ public class TestJettyOSGiBootContextAsService
// to pick up and deploy
options.add(mavenBundle().groupId("org.eclipse.jetty.osgi").artifactId("test-jetty-osgi-context").versionAsInProject().start());
String logLevel = "WARN";
// Enable Logging
if (LOGGING_ENABLED)
{
options.addAll(Arrays.asList(options(
// install log service using pax runners profile abstraction (there
// are more profiles, like DS)
// logProfile(),
// this is how you set the default log level when using pax logging
// (logProfile)
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"))));
}
logLevel = "INFO";
options.addAll(Arrays.asList(options(
// install log service using pax runners profile abstraction (there
// are more profiles, like DS)
// logProfile(),
// this is how you set the default log level when using pax logging
// (logProfile)
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
systemProperty("org.eclipse.jetty.LEVEL").value(logLevel))));
return options.toArray(new Option[options.size()]);
}
@ -142,12 +146,14 @@ public class TestJettyOSGiBootContextAsService
ServiceReference[] refs = bundleContext.getServiceReferences(ContextHandler.class.getName(), null);
Assert.assertNotNull(refs);
Assert.assertEquals(1, refs.length);
String[] keys = refs[0].getPropertyKeys();
//uncomment for debugging
/*
String[] keys = refs[0].getPropertyKeys();
if (keys != null)
{
for (String k : keys)
System.err.println("service property: " + k + ", " + refs[0].getProperty(k));
}
}*/
ContextHandler ch = (ContextHandler) bundleContext.getService(refs[0]);
Assert.assertEquals("/acme", ch.getContextPath());

View File

@ -53,7 +53,6 @@ public class TestJettyOSGiBootCore
public Option[] config()
{
VersionResolver resolver = MavenUtils.asInProject();
System.err.println(resolver.getVersion("org.eclipse.jetty", "jetty-server"));
ArrayList<Option> options = new ArrayList<Option>();
TestOSGiUtil.addMoreOSGiContainers(options);
options.addAll(provisionCoreJetty());

View File

@ -19,9 +19,13 @@
package org.eclipse.jetty.osgi.test;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
import static org.ops4j.pax.exam.CoreOptions.options;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.inject.Inject;
@ -41,7 +45,8 @@ import org.osgi.framework.BundleContext;
@RunWith(JUnit4TestRunner.class)
public class TestJettyOSGiBootSpdy
{
private static final boolean LOGGING_ENABLED = false;
private static final String JETTY_SPDY_PORT = "jetty.spdy.port";
private static final int DEFAULT_JETTY_SPDY_PORT = 9877;
@ -61,6 +66,22 @@ public class TestJettyOSGiBootSpdy
options.add(CoreOptions.junitBundles());
options.addAll(TestJettyOSGiBootCore.httpServiceJetty());
options.addAll(spdyJettyDependencies());
String logLevel = "WARN";
// Enable Logging
if (LOGGING_ENABLED)
logLevel = "INFO";
options.addAll(Arrays.asList(options(
// install log service using pax runners profile abstraction (there
// are more profiles, like DS)
// logProfile(),
// this is how you set the default log level when using pax logging
// (logProfile)
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
systemProperty("org.eclipse.jetty.LEVEL").value(logLevel))));
return options.toArray(new Option[options.size()]);
}

View File

@ -77,18 +77,20 @@ public class TestJettyOSGiBootWebAppAsService
options.addAll(configureJettyHomeAndPort("jetty-selector.xml"));
options.add(CoreOptions.bootDelegationPackages("org.xml.sax", "org.xml.*", "org.w3c.*", "javax.xml.*"));
options.addAll(TestJettyOSGiBootCore.coreJettyDependencies());
// Enable Logging
String logLevel = "WARN";
if (LOGGING_ENABLED)
{
options.addAll(Arrays.asList(options(
// install log service using pax runners profile abstraction (there
// are more profiles, like DS)
// logProfile(),
// this is how you set the default log level when using pax logging
// (logProfile)
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"))));
}
logLevel = "INFO";
options.addAll(Arrays.asList(options(
// install log service using pax runners profile abstraction (there
// are more profiles, like DS)
// logProfile(),
// this is how you set the default log level when using pax logging
// (logProfile)
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
systemProperty("org.eclipse.jetty.LEVEL").value(logLevel))));
options.addAll(jspDependencies());
return options.toArray(new Option[options.size()]);

View File

@ -52,7 +52,7 @@ import org.osgi.framework.BundleContext;
@RunWith(JUnit4TestRunner.class)
public class TestJettyOSGiBootWithJsp
{
private static final boolean LOGGING_ENABLED = true;
private static final boolean LOGGING_ENABLED = false;
private static final boolean REMOTE_DEBUGGING = false;
@ -72,18 +72,21 @@ public class TestJettyOSGiBootWithJsp
options.add(CoreOptions.bootDelegationPackages("org.xml.sax", "org.xml.*", "org.w3c.*", "javax.xml.*"));
options.addAll(TestJettyOSGiBootCore.coreJettyDependencies());
String logLevel = "WARN";
// Enable Logging
if (LOGGING_ENABLED)
{
logLevel = "INFO";
options.addAll(Arrays.asList(options(
// install log service using pax runners profile abstraction (there
// are more profiles, like DS)
// logProfile(),
// this is how you set the default log level when using pax logging
// (logProfile)
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"))));
}
systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value(logLevel),
systemProperty("org.eclipse.jetty.LEVEL").value(logLevel))));
options.addAll(jspDependencies());
// Remote JDWP Debugging, this won't work with the forked container.
@ -119,7 +122,6 @@ public class TestJettyOSGiBootWithJsp
+ etc
+ "/jetty-testrealm.xml";
options.add(systemProperty(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS).value(xmlConfigs));
System.err.println(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS+"="+xmlConfigs);
options.add(systemProperty("jetty.port").value(String.valueOf(TestJettyOSGiBootCore.DEFAULT_JETTY_HTTP_PORT)));
options.add(systemProperty("jetty.home").value(etcFolder.getParentFile().getAbsolutePath()));
return options;
@ -163,10 +165,6 @@ public class TestJettyOSGiBootWithJsp
@Test
public void testJspDump() throws Exception
{
// System.err.println("http://127.0.0.1:9876/jsp/dump.jsp sleeping....");
// Thread.currentThread().sleep(5000000);
// now test the jsp/dump.jsp
HttpClient client = new HttpClient();
try
{
@ -175,7 +173,6 @@ public class TestJettyOSGiBootWithJsp
Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
String content = new String(response.getContent());
System.err.println("content: " + content);
Assert.assertTrue(content.contains("<tr><th>ServletPath:</th><td>/jsp/dump.jsp</td></tr>"));
}
finally

View File

@ -0,0 +1,13 @@
# LOG4J levels: OFF, FATAL, ERROR, WARN, INFO, DEBUG, ALL
#
log4j.rootLogger=ALL,CONSOLE
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
#log4j.appender.CONSOLE.threshold=INFO
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
#log4j.appender.CONSOLE.layout.ConversionPattern=%d %t [%5p][%c{1}] %m%n
log4j.appender.CONSOLE.layout.ConversionPattern=%d [%5p][%c] %m%n
# Level tuning
log4j.logger.org.eclipse.jetty=INFO
log4j.logger.org.ops4j=WARN

View File

@ -391,11 +391,13 @@ public class HttpChannel<T> implements HttpParser.RequestHandler<T>, Runnable
@Override
public String toString()
{
return String.format("%s@%x{r=%s,a=%s}",
return String.format("%s@%x{r=%s,a=%s,uri=%s}",
getClass().getSimpleName(),
hashCode(),
_requests,
_state.getState());
_state.getState(),
_state.getState()==HttpChannelState.State.IDLE?"-":_request.getRequestURI()
);
}
@Override

View File

@ -405,7 +405,7 @@ public class HttpChannelState
public void complete()
{
// just like resume, except don't set _dispatched=true;
boolean dispatch;
boolean handle;
synchronized (this)
{
switch(_state)
@ -421,7 +421,7 @@ public class HttpChannelState
case ASYNCWAIT:
_state=State.COMPLETECALLED;
dispatch=!_expired;
handle=!_expired;
break;
default:
@ -429,10 +429,14 @@ public class HttpChannelState
}
}
if (dispatch)
if (handle)
{
cancelTimeout();
scheduleDispatch();
ContextHandler handler=getContextHandler();
if (handler!=null)
handler.handle(_channel);
else
_channel.handle();
}
}
@ -599,7 +603,11 @@ public class HttpChannelState
{
final AsyncContextEvent event=_event;
if (event!=null)
return ((Context)event.getServletContext()).getContextHandler();
{
Context context=((Context)event.getServletContext());
if (context!=null)
return context.getContextHandler();
}
return null;
}

View File

@ -223,7 +223,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
// Call the channel and this will either handle the request/response to completion OR,
// if the request suspends, the request/response will be incomplete so the outer loop will exit.
boolean handle=_channel.handle();
// Return if suspended or upgraded
if (!handle || getEndPoint().getConnection()!=this)
return;
@ -270,7 +270,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
if (!_channel.getState().isSuspended())
getEndPoint().close();
return;
}
}
}
}
catch (EofException e)
@ -508,13 +508,6 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
getEndPoint().close();
}
}
// make sure that an oshut connection is driven towards close
// TODO this is a little ugly
if (getEndPoint().isOpen() && getEndPoint().isOutputShutdown())
{
fillInterested();
}
}
}
@ -544,7 +537,7 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
// need to call blockForContent again
while (event && BufferUtil.hasContent(_requestBuffer) && _parser.inContentState())
_parser.parseNext(_requestBuffer);
// If we have an event, return
if (event)
return;
@ -625,11 +618,11 @@ public class HttpConnection extends AbstractConnection implements Runnable, Http
*/
releaseRequestBuffer();
}
@Override
public String toString()
{
return super.toString()+"{"+HttpConnection.this+","+getEndPoint()+","+_parser+"}";
return super.toString()+"{"+_channel+","+HttpConnection.this+"}";
}
}

View File

@ -140,7 +140,7 @@ public abstract class HttpInput<T> extends ServletInputStream
// blockForContent will only return with no
// content if it is closed.
if (!isShutdown())
LOG.warn("Unexpected !EOF ");
LOG.warn("Unexpected !EOF: "+this);
onEOF();
return -1;

View File

@ -19,11 +19,9 @@
package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@ -34,22 +32,18 @@ import java.util.TimerTask;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.validation.Schema;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpMethod;
import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.Attributes;
@ -282,9 +276,9 @@ public class Server extends HandlerWrapper implements Attributes
{
if (getStopAtShutdown())
{
ShutdownThread.register(this);
ShutdownThread.register(this);
}
ShutdownMonitor.getInstance().start(); // initialize
LOG.info("jetty-"+getVersion());
@ -318,7 +312,7 @@ public class Server extends HandlerWrapper implements Attributes
if (isDumpAfterStart())
dumpStdErr();
// use DateCache timer for Date field reformat
final HttpFields.DateGenerator date = new HttpFields.DateGenerator();
long now=System.currentTimeMillis();
@ -335,8 +329,8 @@ public class Server extends HandlerWrapper implements Attributes
this.cancel();
}
},tick,1000);
mex.ifExceptionThrow();
}
@ -374,7 +368,7 @@ public class Server extends HandlerWrapper implements Attributes
if (stopTimeout>0)
{
long stop_by=System.currentTimeMillis()+stopTimeout;
LOG.info("Graceful shutdown {} by ",this,new Date(stop_by));
LOG.debug("Graceful shutdown {} by ",this,new Date(stop_by));
// Wait for shutdowns
for (Future<Void> future: futures)
@ -606,10 +600,10 @@ public class Server extends HandlerWrapper implements Attributes
break;
}
}
if (connector==null)
return null;
ContextHandler context = getChildHandlerByClass(ContextHandler.class);
try
@ -621,7 +615,7 @@ public class Server extends HandlerWrapper implements Attributes
host=context.getVirtualHosts()[0];
if (host==null)
host=InetAddress.getLocalHost().getHostAddress();
String path=context==null?null:context.getContextPath();
if (path==null)
path="/";
@ -633,7 +627,7 @@ public class Server extends HandlerWrapper implements Attributes
return null;
}
}
/* ------------------------------------------------------------ */
@Override
public String toString()
@ -646,7 +640,7 @@ public class Server extends HandlerWrapper implements Attributes
{
dumpBeans(out,indent,Collections.singleton(new ClassLoaderDump(this.getClass().getClassLoader())));
}
/* ------------------------------------------------------------ */
public static void main(String...args) throws Exception
{

View File

@ -40,7 +40,6 @@ import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Future;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.FilterRegistration;
@ -104,11 +103,11 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
{
public static int SERVLET_MAJOR_VERSION=3;
public static int SERVLET_MINOR_VERSION=0;
final private static String __unimplmented="Unimplemented - use org.eclipse.jetty.servlet.ServletContextHandler";
private static final Logger LOG = Log.getLogger(ContextHandler.class);
private static final ThreadLocal<Context> __context = new ThreadLocal<Context>();
@ -141,8 +140,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
return c.getContextHandler();
return null;
}
protected Context _scontext;
private final AttributesMap _attributes;
private final Map<String, String> _initParams;
@ -566,7 +565,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
public void addEventListener(EventListener listener)
{
_eventListeners.add(listener);
if (listener instanceof ServletContextListener)
_contextListeners.add((ServletContextListener)listener);
@ -579,7 +578,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (listener instanceof ServletRequestAttributeListener)
_requestAttributeListeners.add((ServletRequestAttributeListener)listener);
}
/* ------------------------------------------------------------ */
/**
* Remove a context event listeners.
@ -592,7 +591,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
public void removeEventListener(EventListener listener)
{
_eventListeners.remove(listener);
if (listener instanceof ServletContextListener)
_contextListeners.remove(listener);
@ -616,13 +615,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
{
_programmaticListeners.add(listener);
}
/* ------------------------------------------------------------ */
protected boolean isProgrammaticListener(EventListener listener)
{
return _programmaticListeners.contains(listener);
}
/* ------------------------------------------------------------ */
/**
* @return true if this context is accepting new requests
@ -725,7 +724,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
startContext();
_availability = Availability.AVAILABLE;
LOG.info("started {}",this);
LOG.info("Started {}", this);
}
finally
{
@ -771,7 +770,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
ServletContextEvent event = new ServletContextEvent(_scontext);
for (ServletContextListener listener:_contextListeners)
callContextInitialized(listener, event);
}
}
}
/* ------------------------------------------------------------ */
@ -818,7 +817,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
if (!_contextListeners.isEmpty())
{
ServletContextEvent event = new ServletContextEvent(_scontext);
for (int i = _contextListeners.size(); i-->0;)
for (int i = _contextListeners.size(); i-->0;)
callContextDestroyed(_contextListeners.get(i),event);
}
@ -831,14 +830,14 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
String name = e.nextElement();
checkManagedAttribute(name,null);
}
for (EventListener l : _programmaticListeners)
removeEventListener(l);
_programmaticListeners.clear();
}
finally
{
LOG.info("stopped {}",this);
LOG.info("Stopped {}", this);
__context.set(old_context);
// reset the classloader
if (_classLoader != null && current_thread!=null)
@ -894,10 +893,10 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
default:
match = contextVhost.equalsIgnoreCase(vhost);
}
if (match)
break loop;
}
if (!match)
return false;
@ -1657,7 +1656,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
return host;
}
/* ------------------------------------------------------------ */
/**
* Add an AliasCheck instance to possibly permit aliased resources
@ -1667,7 +1666,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
{
_aliasChecks.add(check);
}
/* ------------------------------------------------------------ */
/**
* @return Mutable list of Alias checks
@ -1798,7 +1797,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
return null;
return _mimeTypes.getMimeByExtension(file);
}
/* ------------------------------------------------------------ */
/*
* @see javax.servlet.ServletContext#getRequestDispatcher(java.lang.String)
@ -2182,13 +2181,13 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
return _enabled;
}
}
public static class NoContext extends AttributesMap implements ServletContext
{
private int _effectiveMajorVersion = SERVLET_MAJOR_VERSION;
private int _effectiveMinorVersion = SERVLET_MINOR_VERSION;
/* ------------------------------------------------------------ */
public NoContext()
{
@ -2532,8 +2531,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
return null;
}
}
/* ------------------------------------------------------------ */
/** Interface to check aliases
*/
@ -2547,7 +2546,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
*/
boolean check(String path, Resource resource);
}
/* ------------------------------------------------------------ */
/** Approve all aliases.
@ -2560,7 +2559,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
return true;
}
}
/* ------------------------------------------------------------ */
/** Approve Aliases with same suffix.
* Eg. a symbolic link from /foobar.html to /somewhere/wibble.html would be
@ -2578,8 +2577,8 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
return resource.getAlias().toString().endsWith(suffix);
}
}
/* ------------------------------------------------------------ */
/** Approve Aliases with a path prefix.
* Eg. a symbolic link from /dirA/foobar.html to /dirB/foobar.html would be
@ -2599,7 +2598,7 @@ public class ContextHandler extends ScopedHandler implements Attributes, Gracefu
}
/* ------------------------------------------------------------ */
/** Approve Aliases of a non existent directory.
* If a directory "/foobar/" does not exist, then the resource is
* If a directory "/foobar/" does not exist, then the resource is
* aliased to "/foobar". Accept such aliases.
*/
public static class ApproveNonExistentDirectoryAliases implements AliasCheck

View File

@ -27,6 +27,9 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.io.Connection;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Response;
import org.eclipse.jetty.util.DateCache;
@ -40,7 +43,7 @@ import org.eclipse.jetty.util.RolloverFileOutputStream;
* and the current thread name is updated with information that will link
* to the details in that output.
*/
public class DebugHandler extends HandlerWrapper
public class DebugHandler extends HandlerWrapper implements Connection.Listener
{
private DateCache _date=new DateCache("HH:mm:ss", Locale.US);
private OutputStream _out;
@ -69,14 +72,10 @@ public class DebugHandler extends HandlerWrapper
String ex=null;
try
{
long now=System.currentTimeMillis();
final String d=_date.format(now);
final int ms=(int)(now%1000);
if (retry)
_print.println(d+(ms>99?".":(ms>9?".0":".00"))+ms+":"+name+" RETRY");
print(name,"RESUME");
else
_print.println(d+(ms>99?".":(ms>9?".0":".00"))+ms+":"+name+" "+baseRequest.getRemoteAddr()+" "+request.getMethod()+" "+baseRequest.getHeader("Cookie")+"; "+baseRequest.getHeader("User-Agent"));
print(name,"REQUEST "+baseRequest.getRemoteAddr()+" "+request.getMethod()+" "+baseRequest.getHeader("Cookie")+"; "+baseRequest.getHeader("User-Agent"));
thread.setName(name);
getHandler().handle(target,baseRequest,request,response);
@ -104,21 +103,25 @@ public class DebugHandler extends HandlerWrapper
finally
{
thread.setName(old_name);
long now=System.currentTimeMillis();
final String d=_date.format(now);
final int ms=(int)(now%1000);
suspend=baseRequest.getHttpChannelState().isSuspended();
if (suspend)
{
request.setAttribute("org.eclipse.jetty.thread.name",name);
_print.println(d+(ms>99?".":(ms>9?".0":".00"))+ms+":"+name+" SUSPEND");
print(name,"SUSPEND");
}
else
_print.println(d+(ms>99?".":(ms>9?".0":".00"))+ms+":"+name+" "+base_response.getStatus()+
(ex==null?"":("/"+ex))+
" "+base_response.getContentType());
print(name,"RESPONSE "+base_response.getStatus()+(ex==null?"":("/"+ex))+" "+base_response.getContentType());
}
}
private void print(String name,String message)
{
long now=System.currentTimeMillis();
final String d=_date.format(now);
final int ms=(int)(now%1000);
_print.println(d+(ms>99?".":(ms>9?".0":".00"))+ms+":"+name+" "+message);
}
/* (non-Javadoc)
* @see org.eclipse.jetty.server.handler.HandlerWrapper#doStart()
@ -129,6 +132,11 @@ public class DebugHandler extends HandlerWrapper
if (_out==null)
_out=new RolloverFileOutputStream("./logs/yyyy_mm_dd.debug.log",true);
_print=new PrintStream(_out);
for (Connector connector : getServer().getConnectors())
if (connector instanceof AbstractConnector)
((AbstractConnector)connector).addBean(this,false);
super.doStart();
}
@ -140,6 +148,9 @@ public class DebugHandler extends HandlerWrapper
{
super.doStop();
_print.close();
for (Connector connector : getServer().getConnectors())
if (connector instanceof AbstractConnector)
((AbstractConnector)connector).removeBean(this);
}
/**
@ -157,4 +168,17 @@ public class DebugHandler extends HandlerWrapper
{
_out = out;
}
@Override
public void onOpened(Connection connection)
{
print(Thread.currentThread().getName(),"OPENED "+connection.toString());
}
@Override
public void onClosed(Connection connection)
{
print(Thread.currentThread().getName(),"CLOSED "+connection.toString());
}
}

View File

@ -323,17 +323,20 @@ public class JDBCSessionManager extends AbstractSessionManager
super.complete();
try
{
if (_dirty)
if (isValid())
{
//The session attributes have changed, write to the db, ensuring
//http passivation/activation listeners called
willPassivate();
updateSession(this);
didActivate();
}
else if ((getAccessed() - _lastSaved) >= (getSaveInterval() * 1000L))
{
updateSessionAccessTime(this);
if (_dirty)
{
//The session attributes have changed, write to the db, ensuring
//http passivation/activation listeners called
willPassivate();
updateSession(this);
didActivate();
}
else if ((getAccessed() - _lastSaved) >= (getSaveInterval() * 1000L))
{
updateSessionAccessTime(this);
}
}
}
catch (Exception e)

View File

@ -81,7 +81,7 @@ public class HttpConnectionTest
}
@Test
public void testFragmentedChunk()
public void testFragmentedChunk() throws Exception
{
String response=null;
try
@ -119,10 +119,9 @@ public class HttpConnectionTest
}
catch(Exception e)
{
e.printStackTrace();
assertTrue(false);
if (response!=null)
if(response != null)
System.err.println(response);
throw e;
}
}
@ -249,7 +248,7 @@ public class HttpConnectionTest
}
@Test
public void testCharset()
public void testCharset() throws Exception
{
String response=null;
@ -306,10 +305,9 @@ public class HttpConnectionTest
}
catch(Exception e)
{
e.printStackTrace();
assertTrue(false);
if (response!=null)
if(response != null)
System.err.println(response);
throw e;
}
}
@ -391,7 +389,7 @@ public class HttpConnectionTest
}
@Test
public void testConnection()
public void testConnection() throws Exception
{
String response=null;
try
@ -412,10 +410,9 @@ public class HttpConnectionTest
}
catch (Exception e)
{
e.printStackTrace();
assertTrue(false);
if (response!=null)
System.err.println(response);
if(response != null)
System.err.println(response);
throw e;
}
}
@ -525,7 +522,7 @@ public class HttpConnectionTest
}
@Test
public void testAsterisk()
public void testAsterisk() throws Exception
{
String response = null;
@ -572,10 +569,9 @@ public class HttpConnectionTest
}
catch (Exception e)
{
e.printStackTrace();
assertTrue(false);
if (response!=null)
System.err.println(response);
if(response != null)
System.err.println(response);
throw e;
}
finally
{
@ -585,7 +581,7 @@ public class HttpConnectionTest
}
@Test
public void testCONNECT()
public void testCONNECT() throws Exception
{
String response = null;
@ -601,10 +597,9 @@ public class HttpConnectionTest
}
catch (Exception e)
{
e.printStackTrace();
assertTrue(false);
if (response!=null)
System.err.println(response);
if(response != null)
System.err.println(response);
throw e;
}
}

View File

@ -960,7 +960,7 @@ public abstract class HttpServerTestBase extends HttpServerTestFixture
String in = IO.toString(is);
System.err.println(in);
// System.err.println(in);
int index = in.indexOf("123456789");
assertTrue(index > 0);

View File

@ -241,7 +241,7 @@ public class RequestTest
multipart;
String responses=_connector.getResponses(request);
System.err.println(responses);
// System.err.println(responses);
assertTrue(responses.startsWith("HTTP/1.1 200"));
}

View File

@ -122,46 +122,46 @@ public class StressTest
q.clear();
}
@Test
public void testMinNonPersistent() throws Throwable
{
assumeTrue(!OS.IS_OSX);
doThreads(10,10,false);
}
@Test
@Stress("Hey, its called StressTest for a reason")
public void testMinNonPersistent() throws Throwable
{
doThreads(2,2,false);
}
@Test
public void testNonPersistent() throws Throwable
{
// TODO needs to be further investigated
assumeTrue(!OS.IS_OSX || PropertyFlag.isEnabled("test.stress"));
assumeTrue(!OS.IS_OSX);
doThreads(10,10,false);
if (PropertyFlag.isEnabled("test.stress"))
{
doThreads(20,20,false);
Thread.sleep(1000);
doThreads(200,10,false);
Thread.sleep(1000);
doThreads(200,200,false);
}
doThreads(20,20,false);
Thread.sleep(1000);
doThreads(200,10,false);
Thread.sleep(1000);
doThreads(200,200,false);
}
@Test
public void testMinPersistent() throws Throwable
{
// TODO needs to be further investigated
assumeTrue(!OS.IS_OSX);
doThreads(10,10,true);
}
@Test
@Stress("Hey, its called StressTest for a reason")
public void testPersistent() throws Throwable
{
// TODO needs to be further investigated
assumeTrue(!OS.IS_OSX || PropertyFlag.isEnabled("test.stress"));
doThreads(10,10,true);
if (PropertyFlag.isEnabled("test.stress"))
{
doThreads(40,40,true);
Thread.sleep(1000);
doThreads(200,10,true);
Thread.sleep(1000);
doThreads(200,200,true);
}
assumeTrue(!OS.IS_OSX);
doThreads(40,40,true);
Thread.sleep(1000);
doThreads(200,10,true);
Thread.sleep(1000);
doThreads(200,200,true);
}
private void doThreads(int threadCount, final int loops, final boolean persistent) throws Throwable
@ -238,7 +238,6 @@ public class StressTest
{
System.err.println("STALLED!!!");
System.err.println(_server.getThreadPool().toString());
((ServerConnector)(_server.getConnectors()[0])).dump();
Thread.sleep(5000);
System.exit(1);
}

View File

@ -458,7 +458,9 @@ public class StatisticsHandlerTest
{
final long dispatchTime = 10;
final AtomicReference<AsyncContext> asyncHolder = new AtomicReference<>();
final CyclicBarrier barrier[] = {new CyclicBarrier(2), new CyclicBarrier(2), new CyclicBarrier(2)};
final CyclicBarrier barrier[] = {new CyclicBarrier(2), new CyclicBarrier(2)};
final CountDownLatch latch = new CountDownLatch(1);
_statsHandler.setHandler(new AbstractHandler()
{
@Override
@ -540,7 +542,7 @@ public class StatisticsHandlerTest
{
try
{
barrier[2].await();
latch.countDown();
}
catch (Exception ignored)
{
@ -550,7 +552,7 @@ public class StatisticsHandlerTest
long requestTime = 20;
Thread.sleep(requestTime);
asyncHolder.get().complete();
barrier[2].await();
latch.await();
assertEquals(1, _statsHandler.getRequests());
assertEquals(0, _statsHandler.getRequestsActive());

View File

@ -125,7 +125,6 @@ public class SSLEngineTest
{
server.setHandler(new HelloWorldHandler());
server.start();
server.dumpStdErr();
SSLContext ctx=SSLContext.getInstance("TLS");
ctx.init(null,SslContextFactory.TRUST_ALL_CERTS,new java.security.SecureRandom());

View File

@ -76,11 +76,21 @@ public class HttpTransportOverSPDY implements HttpTransport
this.requestHeaders = requestHeaders;
}
protected Stream getStream()
{
return stream;
}
protected Fields getRequestHeaders()
{
return requestHeaders;
}
@Override
public void send(HttpGenerator.ResponseInfo info, ByteBuffer content, boolean lastContent, Callback callback)
{
if (LOG.isDebugEnabled())
LOG.debug("send {} {} {} {} last={}", this, stream, info, BufferUtil.toDetailString(content), lastContent);
LOG.debug("Sending {} {} {} {} last={}", this, stream, info, BufferUtil.toDetailString(content), lastContent);
if (stream.isClosed() || stream.isReset())
{
@ -88,7 +98,6 @@ public class HttpTransportOverSPDY implements HttpTransport
callback.failed(exception);
return;
}
// new Throwable().printStackTrace();
// info==null content==null lastContent==false should not happen
// info==null content==null lastContent==true signals no more content - complete
@ -151,7 +160,7 @@ public class HttpTransportOverSPDY implements HttpTransport
{
// Is the stream still open?
if (stream.isClosed() || stream.isReset())
// tell the callback about the EOF
// tell the callback about the EOF
callback.failed(new EofException("stream closed"));
else
// send the data and let it call the callback
@ -173,7 +182,6 @@ public class HttpTransportOverSPDY implements HttpTransport
else
// No data and no close so tell callback we are completed
callback.succeeded();
}
@Override
@ -190,11 +198,10 @@ public class HttpTransportOverSPDY implements HttpTransport
}
}
@Override
public void completed()
{
LOG.debug("completed");
LOG.debug("Completed");
}
private void reply(Stream stream, ReplyInfo replyInfo)
@ -217,54 +224,61 @@ public class HttpTransportOverSPDY implements HttpTransport
}
}
private class PushHttpTransportOverSPDY extends HttpTransportOverSPDY
private static class PushHttpTransportOverSPDY extends HttpTransportOverSPDY
{
private final PushResourceCoordinator pushResourceCoordinator;
private final PushResourceCoordinator coordinator;
private PushHttpTransportOverSPDY(Connector connector, HttpConfiguration configuration, EndPoint endPoint,
PushStrategy pushStrategy, Stream stream, Fields requestHeaders,
PushResourceCoordinator pushResourceCoordinator)
PushResourceCoordinator coordinator)
{
super(connector, configuration, endPoint, pushStrategy, stream, requestHeaders);
this.pushResourceCoordinator = pushResourceCoordinator;
this.coordinator = coordinator;
}
@Override
public void completed()
{
pushResourceCoordinator.complete();
Stream stream = getStream();
LOG.debug("Resource pushed for {} on {}",
getRequestHeaders().get(HTTPSPDYHeader.URI.name(stream.getSession().getVersion())), stream);
coordinator.complete();
}
}
private class PushResourceCoordinator
{
private final Queue<PushResource> queue = new ConcurrentArrayQueue<>();
private final AtomicBoolean channelActive = new AtomicBoolean(false);
private final Set<String> pushResources;
private final Set<String> resources;
private boolean active;
private PushResourceCoordinator(Set<String> pushResources)
private PushResourceCoordinator(Set<String> resources)
{
this.pushResources = pushResources;
this.resources = resources;
}
private void coordinate()
{
for (String pushResource : pushResources)
// Must send all push frames to the client at once before we
// return from this method and send the main resource data
for (String pushResource : resources)
pushResource(pushResource);
}
private void sendNextResourceData()
{
if (channelActive.compareAndSet(false, true))
PushResource resource;
synchronized (this)
{
PushResource pushResource = queue.poll();
if (pushResource != null)
{
HttpChannelOverSPDY pushChannel = newHttpChannelOverSPDY(pushResource.getPushStream(),
pushResource.getPushRequestHeaders());
pushChannel.requestStart(pushResource.getPushRequestHeaders(), true);
}
if (active)
return;
resource = queue.poll();
if (resource == null)
return;
active = true;
}
HttpChannelOverSPDY pushChannel = newHttpChannelOverSPDY(resource.getPushStream(), resource.getPushRequestHeaders());
pushChannel.requestStart(resource.getPushRequestHeaders(), true);
}
private HttpChannelOverSPDY newHttpChannelOverSPDY(Stream pushStream, Fields pushRequestHeaders)
@ -277,65 +291,66 @@ public class HttpTransportOverSPDY implements HttpTransport
private void pushResource(String pushResource)
{
short version = stream.getSession().getVersion();
final short version = stream.getSession().getVersion();
Fields.Field scheme = requestHeaders.get(HTTPSPDYHeader.SCHEME.name(version));
Fields.Field host = requestHeaders.get(HTTPSPDYHeader.HOST.name(version));
Fields.Field uri = requestHeaders.get(HTTPSPDYHeader.URI.name(version));
Fields pushHeaders = createPushHeaders(scheme, host, pushResource);
final Fields pushHeaders = createPushHeaders(scheme, host, pushResource);
final Fields pushRequestHeaders = createRequestHeaders(scheme, host, uri, pushResource);
stream.push(new PushInfo(pushHeaders, false),
new Promise.Adapter<Stream>()
stream.push(new PushInfo(pushHeaders, false), new Promise.Adapter<Stream>()
{
@Override
public void succeeded(Stream pushStream)
{
LOG.debug("Headers pushed for {} on {}", pushHeaders.get(HTTPSPDYHeader.URI.name(version)), pushStream);
queue.offer(new PushResource(pushStream, pushRequestHeaders));
sendNextResourceData();
}
});
}
public void complete()
private Fields createRequestHeaders(Fields.Field scheme, Fields.Field host, Fields.Field uri, String pushResourcePath)
{
if (channelActive.compareAndSet(true, false))
sendNextResourceData();
final Fields newRequestHeaders = new Fields(requestHeaders, false);
short version = stream.getSession().getVersion();
newRequestHeaders.put(HTTPSPDYHeader.METHOD.name(version), "GET");
newRequestHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
newRequestHeaders.put(scheme);
newRequestHeaders.put(host);
newRequestHeaders.put(HTTPSPDYHeader.URI.name(version), pushResourcePath);
String referrer = scheme.value() + "://" + host.value() + uri.value();
newRequestHeaders.put("referer", referrer);
newRequestHeaders.put("x-spdy-push", "true");
return newRequestHeaders;
}
private Fields createPushHeaders(Fields.Field scheme, Fields.Field host, String pushResourcePath)
{
final Fields pushHeaders = new Fields();
short version = stream.getSession().getVersion();
if (version == SPDY.V2)
pushHeaders.put(HTTPSPDYHeader.URI.name(version), scheme.value() + "://" + host.value() + pushResourcePath);
else
throw new IllegalStateException("No channel was active when complete has been called.");
{
pushHeaders.put(HTTPSPDYHeader.URI.name(version), pushResourcePath);
pushHeaders.put(scheme);
pushHeaders.put(host);
}
return pushHeaders;
}
}
private Fields createRequestHeaders(Fields.Field scheme, Fields.Field host, Fields.Field uri, String pushResourcePath)
{
final Fields newRequestHeaders = new Fields(requestHeaders, false);
short version = stream.getSession().getVersion();
newRequestHeaders.put(HTTPSPDYHeader.METHOD.name(version), "GET");
newRequestHeaders.put(HTTPSPDYHeader.VERSION.name(version), "HTTP/1.1");
newRequestHeaders.put(scheme);
newRequestHeaders.put(host);
newRequestHeaders.put(HTTPSPDYHeader.URI.name(version), pushResourcePath);
String referrer = scheme.value() + "://" + host.value() + uri.value();
newRequestHeaders.put("referer", referrer);
newRequestHeaders.put("x-spdy-push", "true");
return newRequestHeaders;
}
private Fields createPushHeaders(Fields.Field scheme, Fields.Field host, String pushResourcePath)
{
final Fields pushHeaders = new Fields();
short version = stream.getSession().getVersion();
if (version == SPDY.V2)
pushHeaders.put(HTTPSPDYHeader.URI.name(version), scheme.value() + "://" + host.value() + pushResourcePath);
else
private void complete()
{
pushHeaders.put(HTTPSPDYHeader.URI.name(version), pushResourcePath);
pushHeaders.put(scheme);
pushHeaders.put(host);
synchronized (this)
{
active = false;
}
sendNextResourceData();
}
return pushHeaders;
}
private class PushResource
private static class PushResource
{
private final Stream pushStream;
private final Fields pushRequestHeaders;

View File

@ -1,4 +1,26 @@
# Enabled services and configuration needed by the test webapp
OPTIONS=client
etc/test-realm.xml
# ===========================================================
# Enable the demonstration web applications
#
# To disable the demos, either delete this file, move it out of
# the start.d directory or rename it to not end with ".ini"
# ===========================================================
# ===========================================================
# Add a deploy app provider to scan the webapps.demo directory
# -----------------------------------------------------------
etc/jetty-demo.xml
# ===========================================================
# Enable the Jetty HTTP client APIs for use by demo webapps
# -----------------------------------------------------------
OPTIONS=client
# ===========================================================
# Enable the test-realm login service for use by authentication
# demonstrations
# -----------------------------------------------------------
etc/test-realm.xml