Merge remote-tracking branch 'origin/master' into servlet-3.1-api
diff --git a/VERSION.txt b/VERSION.txt
index a6c48bb..4da151f 100644
--- a/VERSION.txt
+++ b/VERSION.txt
@@ -1,3 +1,83 @@
+jetty-9.0.2-SNAPSHOT
+
+
+jetty-9.0.1.v20130408 - 08 April 2013
+ + 384552 add comment to jetty-https.xml describing keymanager password
+ + 385488 non existing resources in collection are just warnings
+ + 392129 fixed merged of handling of timeouts after startAsync
+ + 393971 Improve setParentLoaderPriorty javadoc
+ + 393972 Improve WebAppContext classloading javadoc
+ + 395620 do not managed inherited life cycle listeners
+ + 396562 Add an implementation of RequestLog that supports Slf4j
+ + 399967 Destroyables destroyed on undeploy and shutdown hook
+ + 400142 ConcurrentModificationException in JDBC SessionManger
+ + 400144 When loading a session fails the JDBCSessionManger produces duplicate
+   session IDs
+ + 400689 Add support for Proxy authentication.
+ + 401150 close input stream used from cached resource
+ + 401806 spdy push properly pass through request and response headers for
+   pushed resources
+ + 402397 InputStreamResponseListener early close inputStream cause hold lock.
+ + 402485 reseed secure random
+ + 402626 Do not required endpoint host checking by default in server and
+   configure in client
+ + 402666 Improve handling of TLS exceptions due to raw socket close.
+ + 402694 setuid as LifeCycle listener
+ + 402706 HttpSession.setMaxInactiveInterval(int) does not change JDBCSession
+   expiry
+ + 402726 WebAppContext references old WebSocket packages in system and server
+   classes
+ + 402735 jetty.sh to support status which is == check
+ + 402757 WebSocket client module can't be used with WebSocket server module in
+   the same WAR.
+ + 402833 Test harness for global error page and hide exception message from
+   reason string
+ + 402844 STOP.PORT & STOP.KEY behaviour has changed
+ + 402982 Premature initialization of Servlets
+ + 402984 WebSocket Upgrade must honor case insensitive header fields in
+   upgrade request
+ + 403122 Session replication fails with ClassNotFoundException when session
+   attribute is Java dynamic proxy
+ + 403280 Update to javax.el 2.2.4
+ + 403281 jetty.sh waits for started or failure before returning
+ + 403360 Named connectors
+ + 403370 move frameBytes.fail() call in StandardSession.flush() outside the
+   synchronized block to avoid deadlock
+ + 403373 WebSocket change timeout log level from warn -> info
+ + 403380 Introduce WebSocketTimeoutException to differentiate between EOF on
+   write and Timeout
+ + 403451 Review synchronization in SslConnection.
+ + 403510 HttpSession maxInactiveInterval is not serialized in HashSession
+ + 403513 jetty:run goal cannot be executed twice during the maven build
+ + 403570 Asynchronous Request Logging
+ + 403591 do not use the ConcurrentArrayBlockingQueue for thread pool, selector
+   and async request log
+ + 403817 Use of WebSocket Session.close() results in invalid status code
+ + 404029 port jetty-monitor to jetty-9 and activate it
+ + 404036 JDBCSessionIdManager.doStart() method should not call
+   cleanExpiredSessions() because Listeners can't be notified
+ + 404067 If cannot connect to db fail startup of JDBCSessionIdManager
+ + 404128 Add Vary headers rather than set them
+ + 404176 Jetty's AnnotationConfiguration class does not scan non-jar resources
+   on the container classpath
+ + 404204 Exception from inputstream cause hang or timeout.
+ + 404283 org.eclipse.jetty.util.Scanner.scanFile() dies with an NPE if
+   listFiles() returns null
+ + 404323 Improved parameterization of https and SPDY
+ + 404325 data constraint redirection does send default port
+ + 404326 set status when Request.setHandled(true) is called
+ + 404511 Replaced all StringMap usage with Tries
+ + 404517 Close connection if request received after half close
+ + 404610 Reintroduce ability to disallow TLS renegotiation.
+ + 404757 SPDY can only be built with the latest JDK version.
+ + 404789 Support IPv6 addresses in DoSFilter white list.
+ + 404881 Allow regexs for SslContextFactory.setIncludeCipherSuites() and
+   .setExcludeCipherSuites()
+ + 404889 SelectorManager accepts attachments with sockets
+ + 404906 servlets with load-on-startup = 0 are not fired up on jetty 9 startup
+ + 404958 Fixed Resource.newSystemResource striped / handling
+ + 405044 Query parameters lost for non GET or POST.
+
 jetty-9.0.0.v20130308 - 08 March 2013
  + 399070 add updated version of npn-boot jar to start.ini
  + 399799 do not hold lock while calling invalidation listeners
@@ -34,10 +114,10 @@
    upstream server. Fix several other small proxy issues
  + 402316 HttpReceiver and null pointer exception.
  + 402341 Host with default port causes redirects loop.
- + 402726 WebAppContext references old WebSocket packages in system and
-   server classes
- + 402757 WebSocket client module can't be used with WebSocket server
-   module in the same WAR
+ + 402726 WebAppContext references old WebSocket packages in system and server
+   classes
+ + 402757 WebSocket client module can't be used with WebSocket server module in
+   the same WAR
 
 jetty-8.1.10.v20130312 - 12 March 2013
  + 376273 Early EOF because of SSL Protocol Error on
diff --git a/aggregates/jetty-all/pom.xml b/aggregates/jetty-all/pom.xml
index 43e0177..6ad817d 100644
--- a/aggregates/jetty-all/pom.xml
+++ b/aggregates/jetty-all/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../../pom.xml</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>
diff --git a/examples/async-rest/async-rest-jar/pom.xml b/examples/async-rest/async-rest-jar/pom.xml
index 56f14d3..79618bb 100644
--- a/examples/async-rest/async-rest-jar/pom.xml
+++ b/examples/async-rest/async-rest-jar/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>example-async-rest</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>  
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.eclipse.jetty.example-async-rest</groupId>
diff --git a/examples/async-rest/async-rest-webapp/pom.xml b/examples/async-rest/async-rest-webapp/pom.xml
index d2e1815..866339d 100644
--- a/examples/async-rest/async-rest-webapp/pom.xml
+++ b/examples/async-rest/async-rest-webapp/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>example-async-rest</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>  
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.eclipse.jetty.example-async-rest</groupId>
diff --git a/examples/async-rest/pom.xml b/examples/async-rest/pom.xml
index 7118c51..082de5c 100644
--- a/examples/async-rest/pom.xml
+++ b/examples/async-rest/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty.examples</groupId>
     <artifactId>examples-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>  
   <modelVersion>4.0.0</modelVersion>
diff --git a/examples/embedded/pom.xml b/examples/embedded/pom.xml
index 02b939b..498e11d 100644
--- a/examples/embedded/pom.xml
+++ b/examples/embedded/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty.examples</groupId>
     <artifactId>examples-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>
diff --git a/examples/pom.xml b/examples/pom.xml
index f93d566..a5d95ba 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
   <groupId>org.eclipse.jetty.examples</groupId>
diff --git a/jetty-annotations/pom.xml b/jetty-annotations/pom.xml
index ad08f18..32bb8c6 100644
--- a/jetty-annotations/pom.xml
+++ b/jetty-annotations/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-annotations</artifactId>
diff --git a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
index f8c4e2b..f76eadf 100644
--- a/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
+++ b/jetty-annotations/src/main/java/org/eclipse/jetty/annotations/WebServletAnnotation.java
@@ -167,7 +167,7 @@
             //if not, add it
             for (WebInitParam ip:annotation.initParams())
             {
-                if (metaData.getOrigin(servletName+".servlet.init-param"+ip.name())==Origin.NotSet)
+                if (metaData.getOrigin(servletName+".servlet.init-param."+ip.name())==Origin.NotSet)
                 {
                     holder.setInitParameter(ip.name(), ip.value());
                     metaData.setOrigin(servletName+".servlet.init-param."+ip.name());
diff --git a/jetty-ant/pom.xml b/jetty-ant/pom.xml
index fb55b41..80f05c5 100755
--- a/jetty-ant/pom.xml
+++ b/jetty-ant/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-ant</artifactId>
diff --git a/jetty-client/pom.xml b/jetty-client/pom.xml
index bac8551..c1236c3 100644
--- a/jetty-client/pom.xml
+++ b/jetty-client/pom.xml
@@ -2,7 +2,7 @@
     <parent>
         <groupId>org.eclipse.jetty</groupId>
         <artifactId>jetty-project</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
index 953855a..dd2c7bc 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java
@@ -966,6 +966,7 @@
                     engine.setUseClientMode(true);
 
                     SslConnection sslConnection = newSslConnection(HttpClient.this, endPoint, engine);
+                    sslConnection.setRenegotiationAllowed(sslContextFactory.isRenegotiationAllowed());
                     EndPoint appEndPoint = sslConnection.getDecryptedEndPoint();
                     HttpConnection connection = newHttpConnection(HttpClient.this, appEndPoint, destination);
 
diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java
index ad96efb..ca61d22 100644
--- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java
+++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java
@@ -191,25 +191,17 @@
                     params.append("&");
             }
 
-            // Behave as a GET, adding the params to the path, if it's a POST with some content
-            if (method == HttpMethod.POST && request.getContent() != null)
-                method = HttpMethod.GET;
-
-            switch (method)
+            // POST with no content, send parameters as body
+            if (method == HttpMethod.POST && request.getContent() == null)
             {
-                case GET:
-                {
-                    path += "?";
-                    path += params.toString();
-                    request.path(path);
-                    break;
-                }
-                case POST:
-                {
-                    request.header(HttpHeader.CONTENT_TYPE, MimeTypes.Type.FORM_ENCODED.asString());
-                    request.content(new StringContentProvider(params.toString()));
-                    break;
-                }
+                request.header(HttpHeader.CONTENT_TYPE, MimeTypes.Type.FORM_ENCODED.asString());
+                request.content(new StringContentProvider(params.toString()));
+            }
+            else
+            {
+                path += "?";
+                path += params.toString();
+                request.path(path);
             }
         }
 
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
index 2250780..f01693d 100644
--- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientTest.java
@@ -255,6 +255,38 @@
     }
 
     @Test
+    public void test_PUT_WithParameters() throws Exception
+    {
+        final String paramName = "a";
+        final String paramValue = "\u20AC";
+        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);
+                String value = request.getParameter(paramName);
+                if (paramValue.equals(value))
+                {
+                    response.setCharacterEncoding("UTF-8");
+                    response.setContentType("text/plain");
+                    response.getOutputStream().print(value);
+                }
+            }
+        });
+
+        URI uri = URI.create(scheme + "://localhost:" + connector.getLocalPort() + "/path?" + paramName + "=" + paramValue);
+        ContentResponse response = client.newRequest(uri)
+                .method(HttpMethod.PUT)
+                .timeout(5, TimeUnit.SECONDS)
+                .send();
+
+        Assert.assertNotNull(response);
+        Assert.assertEquals(200, response.getStatus());
+        Assert.assertEquals(paramValue, new String(response.getContent(), "UTF-8"));
+    }
+
+    @Test
     public void test_POST_WithParameters_WithContent() throws Exception
     {
         final byte[] content = {0, 1, 2, 3};
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesClientTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesClientTest.java
new file mode 100644
index 0000000..67c9931
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesClientTest.java
@@ -0,0 +1,369 @@
+//
+//  ========================================================================
+//  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.ssl;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.SocketTimeoutException;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLServerSocket;
+import javax.net.ssl.SSLSocket;
+
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.client.api.ContentResponse;
+import org.eclipse.jetty.client.api.Request;
+import org.eclipse.jetty.client.util.FutureResponseListener;
+import org.eclipse.jetty.http.HttpScheme;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
+import org.eclipse.jetty.util.ssl.SslContextFactory;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+public class SslBytesClientTest extends SslBytesTest
+{
+    private ExecutorService threadPool;
+    private HttpClient client;
+    private SslContextFactory sslContextFactory;
+    private SSLServerSocket acceptor;
+    private SimpleProxy proxy;
+
+    @Before
+    public void init() throws Exception
+    {
+        threadPool = Executors.newCachedThreadPool();
+
+        client = new HttpClient(new SslContextFactory(true));
+        client.setMaxConnectionsPerDestination(1);
+        File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks");
+        sslContextFactory = client.getSslContextFactory();
+        sslContextFactory.setKeyStorePath(keyStore.getAbsolutePath());
+        sslContextFactory.setKeyStorePassword("storepwd");
+        client.start();
+
+        SSLContext sslContext = sslContextFactory.getSslContext();
+        acceptor = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket(43191);
+
+        int serverPort = acceptor.getLocalPort();
+
+        proxy = new SimpleProxy(threadPool, "localhost", serverPort);
+        proxy.start();
+        logger.info(":{} <==> :{}", proxy.getPort(), serverPort);
+    }
+
+    @After
+    public void destroy() throws Exception
+    {
+        if (acceptor != null)
+            acceptor.close();
+        if (proxy != null)
+            proxy.stop();
+        if (client != null)
+            client.stop();
+        if (threadPool != null)
+            threadPool.shutdownNow();
+    }
+
+    @Test
+    public void testHandshake() throws Exception
+    {
+        Request request = client.newRequest("localhost", proxy.getPort());
+        FutureResponseListener listener = new FutureResponseListener(request);
+        request.scheme(HttpScheme.HTTPS.asString()).send(listener);
+
+        Assert.assertTrue(proxy.awaitClient(5, TimeUnit.SECONDS));
+
+        final SSLSocket server = (SSLSocket)acceptor.accept();
+        server.setUseClientMode(false);
+
+        Future<Object> handshake = threadPool.submit(new Callable<Object>()
+        {
+            public Object call() throws Exception
+            {
+                server.startHandshake();
+                return null;
+            }
+        });
+
+        // Client Hello
+        TLSRecord record = proxy.readFromClient();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToServer(record);
+
+        // Server Hello + Certificate + Server Done
+        record = proxy.readFromServer();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToClient(record);
+
+        // Client Key Exchange
+        record = proxy.readFromClient();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToServer(record);
+
+        // Change Cipher Spec
+        record = proxy.readFromClient();
+        Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType());
+        proxy.flushToServer(record);
+
+        // Client Done
+        record = proxy.readFromClient();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToServer(record);
+
+        // Change Cipher Spec
+        record = proxy.readFromServer();
+        Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType());
+        proxy.flushToClient(record);
+
+        // Server Done
+        record = proxy.readFromServer();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToClient(record);
+
+        Assert.assertNull(handshake.get(5, TimeUnit.SECONDS));
+
+        SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
+        // Read request
+        BufferedReader reader = new BufferedReader(new InputStreamReader(server.getInputStream(), "UTF-8"));
+        String line = reader.readLine();
+        Assert.assertTrue(line.startsWith("GET"));
+        while (line.length() > 0)
+            line = reader.readLine();
+
+        // Write response
+        OutputStream output = server.getOutputStream();
+        output.write(("HTTP/1.1 200 OK\r\n" +
+                "Content-Length: 0\r\n" +
+                "\r\n").getBytes("UTF-8"));
+        output.flush();
+        Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
+
+        ContentResponse response = listener.get(5, TimeUnit.SECONDS);
+        Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
+
+        server.close();
+    }
+
+    @Test
+    public void testServerRenegotiation() throws Exception
+    {
+        Request request = client.newRequest("localhost", proxy.getPort());
+        FutureResponseListener listener = new FutureResponseListener(request);
+        request.scheme(HttpScheme.HTTPS.asString()).send(listener);
+
+        Assert.assertTrue(proxy.awaitClient(5, TimeUnit.SECONDS));
+
+        final SSLSocket server = (SSLSocket)acceptor.accept();
+        server.setUseClientMode(false);
+
+        Future<Object> handshake = threadPool.submit(new Callable<Object>()
+        {
+            public Object call() throws Exception
+            {
+                server.startHandshake();
+                return null;
+            }
+        });
+
+        SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
+        Assert.assertNull(handshake.get(5, TimeUnit.SECONDS));
+
+        // Read request
+        InputStream serverInput = server.getInputStream();
+        BufferedReader reader = new BufferedReader(new InputStreamReader(serverInput, "UTF-8"));
+        String line = reader.readLine();
+        Assert.assertTrue(line.startsWith("GET"));
+        while (line.length() > 0)
+            line = reader.readLine();
+
+        OutputStream serverOutput = server.getOutputStream();
+        byte[] data1 = new byte[1024];
+        Arrays.fill(data1, (byte)'X');
+        String content1 = new String(data1, "UTF-8");
+        byte[] data2 = new byte[1024];
+        Arrays.fill(data2, (byte)'Y');
+        final String content2 = new String(data2, "UTF-8");
+        // Write first part of the response
+        serverOutput.write(("HTTP/1.1 200 OK\r\n" +
+                "Content-Type: text/plain\r\n" +
+                "Content-Length: " + (content1.length() + content2.length()) + "\r\n" +
+                "\r\n" +
+                content1).getBytes("UTF-8"));
+        serverOutput.flush();
+        Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
+
+        // Renegotiate
+        Future<Object> renegotiation = threadPool.submit(new Callable<Object>()
+        {
+            public Object call() throws Exception
+            {
+                server.startHandshake();
+                return null;
+            }
+        });
+
+        // Renegotiation Handshake
+        TLSRecord record = proxy.readFromServer();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToClient(record);
+
+        // Renegotiation Handshake
+        record = proxy.readFromClient();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToServer(record);
+
+        // Trigger a read to have the server write the final renegotiation steps
+        server.setSoTimeout(100);
+        try
+        {
+            serverInput.read();
+            Assert.fail();
+        }
+        catch (SocketTimeoutException x)
+        {
+            // Expected
+        }
+
+        // Renegotiation Handshake
+        record = proxy.readFromServer();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToClient(record);
+
+        // Renegotiation Change Cipher
+        record = proxy.readFromServer();
+        Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType());
+        proxy.flushToClient(record);
+
+        // Renegotiation Handshake
+        record = proxy.readFromServer();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToClient(record);
+
+        // Renegotiation Change Cipher
+        record = proxy.readFromClient();
+        Assert.assertEquals(TLSRecord.Type.CHANGE_CIPHER_SPEC, record.getType());
+        proxy.flushToServer(record);
+
+        // Renegotiation Handshake
+        record = proxy.readFromClient();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToServer(record);
+
+        Assert.assertNull(renegotiation.get(5, TimeUnit.SECONDS));
+
+        // Complete the response
+        automaticProxyFlow = proxy.startAutomaticFlow();
+        serverOutput.write(data2);
+        serverOutput.flush();
+        Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
+
+        ContentResponse response = listener.get(5, TimeUnit.SECONDS);
+        Assert.assertEquals(HttpStatus.OK_200, response.getStatus());
+        Assert.assertEquals(data1.length + data2.length, response.getContent().length);
+
+        server.close();
+    }
+
+    @Test
+    public void testServerRenegotiationWhenRenegotiationIsForbidden() throws Exception
+    {
+        sslContextFactory.setRenegotiationAllowed(false);
+
+        Request request = client.newRequest("localhost", proxy.getPort());
+        FutureResponseListener listener = new FutureResponseListener(request);
+        request.scheme(HttpScheme.HTTPS.asString()).send(listener);
+
+        Assert.assertTrue(proxy.awaitClient(5, TimeUnit.SECONDS));
+
+        final SSLSocket server = (SSLSocket)acceptor.accept();
+        server.setUseClientMode(false);
+
+        Future<Object> handshake = threadPool.submit(new Callable<Object>()
+        {
+            public Object call() throws Exception
+            {
+                server.startHandshake();
+                return null;
+            }
+        });
+
+        SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
+        Assert.assertNull(handshake.get(5, TimeUnit.SECONDS));
+
+        // Read request
+        InputStream serverInput = server.getInputStream();
+        BufferedReader reader = new BufferedReader(new InputStreamReader(serverInput, "UTF-8"));
+        String line = reader.readLine();
+        Assert.assertTrue(line.startsWith("GET"));
+        while (line.length() > 0)
+            line = reader.readLine();
+
+        OutputStream serverOutput = server.getOutputStream();
+        byte[] data1 = new byte[1024];
+        Arrays.fill(data1, (byte)'X');
+        String content1 = new String(data1, "UTF-8");
+        byte[] data2 = new byte[1024];
+        Arrays.fill(data2, (byte)'Y');
+        final String content2 = new String(data2, "UTF-8");
+        // Write first part of the response
+        serverOutput.write(("HTTP/1.1 200 OK\r\n" +
+                "Content-Type: text/plain\r\n" +
+                "Content-Length: " + (content1.length() + content2.length()) + "\r\n" +
+                "\r\n" +
+                content1).getBytes("UTF-8"));
+        serverOutput.flush();
+        Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
+
+        // Renegotiate
+        threadPool.submit(new Callable<Object>()
+        {
+            public Object call() throws Exception
+            {
+                server.startHandshake();
+                return null;
+            }
+        });
+
+        // Renegotiation Handshake
+        TLSRecord record = proxy.readFromServer();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToClient(record);
+
+        record = proxy.readFromClient();
+        Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
+        proxy.flushToServer(record);
+
+        record = proxy.readFromClient();
+        Assert.assertNull(record);
+        proxy.flushToServer(record);
+
+        server.close();
+    }
+}
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslBytesServerTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java
similarity index 94%
rename from jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslBytesServerTest.java
rename to jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java
index 4a89456..1faca02 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslBytesServerTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesServerTest.java
@@ -16,7 +16,7 @@
 //  ========================================================================
 //
 
-package org.eclipse.jetty.server.ssl;
+package org.eclipse.jetty.client.ssl;
 
 import java.io.BufferedReader;
 import java.io.EOFException;
@@ -84,7 +84,7 @@
     private final int idleTimeout = 2000;
     private ExecutorService threadPool;
     private Server server;
-    private int serverPort;
+    private SslContextFactory sslContextFactory;
     private SSLContext sslContext;
     private SimpleProxy proxy;
 
@@ -94,11 +94,10 @@
         threadPool = Executors.newCachedThreadPool();
         server = new Server();
 
-        File keyStore = MavenTestingUtils.getTestResourceFile("keystore");
-        SslContextFactory sslContextFactory = new SslContextFactory();
+        File keyStore = MavenTestingUtils.getTestResourceFile("keystore.jks");
+        sslContextFactory = new SslContextFactory();
         sslContextFactory.setKeyStorePath(keyStore.getAbsolutePath());
         sslContextFactory.setKeyStorePassword("storepwd");
-        sslContextFactory.setKeyManagerPassword("keypwd");
 
         HttpConnectionFactory httpFactory = new HttpConnectionFactory()
         {
@@ -204,7 +203,7 @@
             }
         });
         server.start();
-        serverPort = connector.getLocalPort();
+        int serverPort = connector.getLocalPort();
 
         sslContext = sslContextFactory.getSslContext();
 
@@ -1278,6 +1277,98 @@
     }
 
     @Test
+    public void testRequestWithContentWithRenegotiationInMiddleOfContentWhenRenegotiationIsForbidden() throws Exception
+    {
+        assumeJavaVersionSupportsTLSRenegotiations();
+
+        sslContextFactory.setRenegotiationAllowed(false);
+
+        final SSLSocket client = newClient();
+        final OutputStream clientOutput = client.getOutputStream();
+
+        SimpleProxy.AutomaticFlow automaticProxyFlow = proxy.startAutomaticFlow();
+        client.startHandshake();
+        Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
+
+        byte[] data1 = new byte[1024];
+        Arrays.fill(data1, (byte)'X');
+        String content1 = new String(data1, "UTF-8");
+        byte[] data2 = new byte[1024];
+        Arrays.fill(data2, (byte)'Y');
+        final String content2 = new String(data2, "UTF-8");
+
+        // Write only part of the body
+        automaticProxyFlow = proxy.startAutomaticFlow();
+        clientOutput.write(("" +
+                "POST / HTTP/1.1\r\n" +
+                "Host: localhost\r\n" +
+                "Content-Type: text/plain\r\n" +
+                "Content-Length: " + (content1.length() + content2.length()) + "\r\n" +
+                "\r\n" +
+                content1).getBytes("UTF-8"));
+        clientOutput.flush();
+        Assert.assertTrue(automaticProxyFlow.stop(5, TimeUnit.SECONDS));
+
+        // Renegotiate
+        threadPool.submit(new Callable<Object>()
+        {
+            @Override
+            public Object call() throws Exception
+            {
+                client.startHandshake();
+                return null;
+            }
+        });
+
+        // Renegotiation Handshake
+        TLSRecord record = proxy.readFromClient();
+        Assert.assertEquals(TLSRecord.Type.HANDSHAKE, record.getType());
+        proxy.flushToServer(record);
+
+        // Renegotiation now allowed, server has closed
+        record = proxy.readFromServer();
+        Assert.assertEquals(TLSRecord.Type.ALERT, record.getType());
+        proxy.flushToClient(record);
+
+        record = proxy.readFromServer();
+        Assert.assertNull(record);
+
+        // Write the rest of the request
+        threadPool.submit(new Callable<Object>()
+        {
+            @Override
+            public Object call() throws Exception
+            {
+                clientOutput.write(content2.getBytes("UTF-8"));
+                clientOutput.flush();
+                return null;
+            }
+        });
+
+        // Trying to write more application data results in an exception since the server closed
+        record = proxy.readFromClient();
+        proxy.flushToServer(record);
+        try
+        {
+            record = proxy.readFromClient();
+            Assert.assertNotNull(record);
+            proxy.flushToServer(record);
+            Assert.fail();
+        }
+        catch (IOException expected)
+        {
+        }
+
+        // Check that we did not spin
+        TimeUnit.MILLISECONDS.sleep(500);
+        Assert.assertThat(sslFills.get(), Matchers.lessThan(50));
+        Assert.assertThat(sslFlushes.get(), Matchers.lessThan(20));
+        Assert.assertThat(httpParses.get(), Matchers.lessThan(50));
+
+        client.close();
+    }
+
+    @Test
     public void testRequestWithBigContentWithRenegotiationInMiddleOfContent() throws Exception
     {
         assumeJavaVersionSupportsTLSRenegotiations();
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslBytesTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesTest.java
similarity index 98%
rename from jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslBytesTest.java
rename to jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesTest.java
index a3b4952..c7fe744 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/ssl/SslBytesTest.java
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ssl/SslBytesTest.java
@@ -16,7 +16,7 @@
 //  ========================================================================
 //
 
-package org.eclipse.jetty.server.ssl;
+package org.eclipse.jetty.client.ssl;
 
 import java.io.EOFException;
 import java.io.IOException;
@@ -115,8 +115,8 @@
 
         public void start() throws Exception
         {
-//            serverSocket = new ServerSocket(5871);
-            serverSocket = new ServerSocket(0);
+            serverSocket = new ServerSocket(47009);
+//            serverSocket = new ServerSocket(0);
             Thread acceptor = new Thread(this);
             acceptor.start();
             server = new Socket(serverHost, serverPort);
diff --git a/jetty-client/src/test/resources/keystore b/jetty-client/src/test/resources/keystore
deleted file mode 100644
index 3a15d1b..0000000
--- a/jetty-client/src/test/resources/keystore
+++ /dev/null
Binary files differ
diff --git a/jetty-continuation/pom.xml b/jetty-continuation/pom.xml
index 0763a02..e146ba8 100644
--- a/jetty-continuation/pom.xml
+++ b/jetty-continuation/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-continuation</artifactId>
diff --git a/jetty-deploy/pom.xml b/jetty-deploy/pom.xml
index cc8a10e..55848f5 100644
--- a/jetty-deploy/pom.xml
+++ b/jetty-deploy/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-deploy</artifactId>
diff --git a/jetty-distribution/pom.xml b/jetty-distribution/pom.xml
index 3f9ba0a..dfe828f 100644
--- a/jetty-distribution/pom.xml
+++ b/jetty-distribution/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>jetty-distribution</artifactId>
   <name>Jetty :: Distribution Assemblies</name>
diff --git a/jetty-http/pom.xml b/jetty-http/pom.xml
index 5b5585f..1403df1 100644
--- a/jetty-http/pom.xml
+++ b/jetty-http/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <artifactId>jetty-project</artifactId>
     <groupId>org.eclipse.jetty</groupId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-http</artifactId>
diff --git a/jetty-io/pom.xml b/jetty-io/pom.xml
index 2c9377e..24eedb6 100644
--- a/jetty-io/pom.xml
+++ b/jetty-io/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <artifactId>jetty-project</artifactId>
     <groupId>org.eclipse.jetty</groupId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-io</artifactId>
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java
index 7549903..4ec1d84 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/AbstractEndPoint.java
@@ -142,14 +142,11 @@
     @Override
     protected void onIdleExpired(TimeoutException timeout)
     {
-        if (isOutputShutdown() || _fillInterest.isInterested() || _writeFlusher.isInProgress())
-        {
-            boolean output_shutdown=isOutputShutdown();
-            _fillInterest.onFail(timeout);
-            _writeFlusher.onFail(timeout);
-            if (output_shutdown)
-                close();
-        }
+        boolean output_shutdown=isOutputShutdown();
+        _fillInterest.onFail(timeout);
+        _writeFlusher.onFail(timeout);
+        if (output_shutdown)
+            close();
     }
 
     @Override
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java b/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java
index 1a1f7f4..317c55e 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/SelectorManager.java
@@ -167,6 +167,20 @@
         selector.submit(selector.new Accept(channel));
     }
 
+    /**
+     * <p>Registers a channel to perform non-blocking read/write operations.</p>
+     * <p>This method is called just after a channel has been accepted by {@link ServerSocketChannel#accept()},
+     * or just after having performed a blocking connect via {@link Socket#connect(SocketAddress, int)}.</p>
+     *
+     * @param channel the channel to register
+     * @param attachment An attachment to be passed via the selection key to the {@link SelectorManager#newConnection(SocketChannel, EndPoint, Object)} method.
+     */
+    public void accept(final SocketChannel channel, Object attachment)
+    {
+        final ManagedSelector selector = chooseSelector();
+        selector.submit(selector.new Accept(channel, attachment));
+    }
+    
     @Override
     protected void doStart() throws Exception
     {
@@ -685,10 +699,18 @@
         private class Accept implements Runnable
         {
             private final SocketChannel _channel;
+            private final Object _attachment;
 
             public Accept(SocketChannel channel)
             {
                 this._channel = channel;
+                this._attachment = null;
+            }
+            
+            public Accept(SocketChannel channel, Object attachment)
+            {
+                this._channel = channel;
+                this._attachment = attachment;
             }
 
             @Override
@@ -696,7 +718,7 @@
             {
                 try
                 {
-                    SelectionKey key = _channel.register(_selector, 0, null);
+                    SelectionKey key = _channel.register(_selector, 0, _attachment);
                     EndPoint endpoint = createEndPoint(_channel, key);
                     key.attach(endpoint);
                 }
diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java
index 9d13a1a..4fca18f 100644
--- a/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java
+++ b/jetty-io/src/main/java/org/eclipse/jetty/io/ssl/SslConnection.java
@@ -99,6 +99,7 @@
             _decryptedEndPoint.getWriteFlusher().completeWrite();
         }
     };
+    private boolean _renegotiationAllowed;
 
     public SslConnection(ByteBufferPool byteBufferPool, Executor executor, EndPoint endPoint, SSLEngine sslEngine)
     {
@@ -137,6 +138,16 @@
         return _decryptedEndPoint;
     }
 
+    public boolean isRenegotiationAllowed()
+    {
+        return _renegotiationAllowed;
+    }
+
+    public void setRenegotiationAllowed(boolean renegotiationAllowed)
+    {
+        this._renegotiationAllowed = renegotiationAllowed;
+    }
+
     @Override
     public void onOpen()
     {
@@ -242,6 +253,7 @@
         private boolean _fillRequiresFlushToProgress;
         private boolean _flushRequiresFillToProgress;
         private boolean _cannotAcceptMoreAppDataToFlush;
+        private boolean _handshaken;
         private boolean _underFlown;
 
         private final Callback _writeCallback = new Callback()
@@ -493,15 +505,19 @@
                     if (DEBUG)
                         LOG.debug("{} unwrap {}", SslConnection.this, unwrapResult);
 
+                    Status unwrapResultStatus = unwrapResult.getStatus();
+                    HandshakeStatus unwrapHandshakeStatus = unwrapResult.getHandshakeStatus();
+                    HandshakeStatus handshakeStatus = _sslEngine.getHandshakeStatus();
+
                     // and deal with the results
-                    switch (unwrapResult.getStatus())
+                    switch (unwrapResultStatus)
                     {
                         case BUFFER_OVERFLOW:
                             throw new IllegalStateException();
 
                         case CLOSED:
                             // Dang! we have to care about the handshake state specially for close
-                            switch (_sslEngine.getHandshakeStatus())
+                            switch (handshakeStatus)
                             {
                                 case NOT_HANDSHAKING:
                                     // We were not handshaking, so just tell the app we are closed
@@ -521,10 +537,28 @@
                             throw new IllegalStateException();
 
                         default:
-                            if (unwrapResult.getStatus()==Status.BUFFER_UNDERFLOW)
-                                _underFlown=true;
+                            if (unwrapHandshakeStatus == HandshakeStatus.FINISHED && !_handshaken)
+                            {
+                                _handshaken = true;
+                                if (DEBUG)
+                                    LOG.debug("{} handshake completed client-side", SslConnection.this);
+                            }
 
-                            // if we produced bytes, we don't care about the handshake state for now and it can be dealt with on another call to fill or flush
+                            // Check whether renegotiation is allowed
+                            if (_handshaken && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING && !isRenegotiationAllowed())
+                            {
+                                if (DEBUG)
+                                    LOG.debug("{} renegotiation denied", SslConnection.this);
+                                closeInbound();
+                                return -1;
+                            }
+
+                            if (unwrapResultStatus == Status.BUFFER_UNDERFLOW)
+                                _underFlown = true;
+
+                            // If bytes were produced, don't bother with the handshake status;
+                            // pass the decrypted data to the application, which will perform
+                            // another call to fill() or flush().
                             if (unwrapResult.bytesProduced() > 0)
                             {
                                 if (app_in == buffer)
@@ -533,7 +567,7 @@
                             }
 
                             // Dang! we have to care about the handshake state
-                            switch (_sslEngine.getHandshakeStatus())
+                            switch (handshakeStatus)
                             {
                                 case NOT_HANDSHAKING:
                                     // we just didn't read anything.
@@ -553,7 +587,7 @@
                                     // we need to send some handshake data
 
                                     // if we are called from flush
-                                    if (buffer==__FLUSH_CALLED_FILL)
+                                    if (buffer == __FLUSH_CALLED_FILL)
                                         return 0; // let it do the wrapping
 
                                     _fillRequiresFlushToProgress = true;
@@ -661,7 +695,6 @@
 
                 while (true)
                 {
-                    // do the funky SSL thang!
                     // We call sslEngine.wrap to try to take bytes from appOut buffers and encrypt them into the _netOut buffer
                     BufferUtil.compact(_encryptedOutput);
                     int pos = BufferUtil.flipToFill(_encryptedOutput);
@@ -672,18 +705,20 @@
                     if (wrapResult.bytesConsumed()>0)
                         consumed+=wrapResult.bytesConsumed();
 
-                    boolean all_consumed=true;
+                    boolean allConsumed=true;
                     // clear empty buffers to prevent position creeping up the buffer
                     for (ByteBuffer b : appOuts)
                     {
                         if (BufferUtil.isEmpty(b))
                             BufferUtil.clear(b);
                         else
-                            all_consumed=false;
+                            allConsumed=false;
                     }
 
+                    Status wrapResultStatus = wrapResult.getStatus();
+
                     // and deal with the results returned from the sslEngineWrap
-                    switch (wrapResult.getStatus())
+                    switch (wrapResultStatus)
                     {
                         case CLOSED:
                             // The SSL engine has close, but there may be close handshake that needs to be written
@@ -692,32 +727,51 @@
                                 _cannotAcceptMoreAppDataToFlush = true;
                                 getEndPoint().flush(_encryptedOutput);
                                 // If we failed to flush the close handshake then we will just pretend that
-                                // the write has progressed normally and let a subsequent call to flush (or WriteFlusher#onIncompleteFlushed)
-                                // to finish writing the close handshake.   The caller will find out about the close on a subsequent flush or fill.
+                                // the write has progressed normally and let a subsequent call to flush
+                                // (or WriteFlusher#onIncompleteFlushed) to finish writing the close handshake.
+                                // The caller will find out about the close on a subsequent flush or fill.
                                 if (BufferUtil.hasContent(_encryptedOutput))
                                     return false;
                             }
 
                             // otherwise we have written, and the caller will close the underlying connection
-                            return all_consumed;
+                            return allConsumed;
 
                         case BUFFER_UNDERFLOW:
                             throw new IllegalStateException();
 
                         default:
                             if (DEBUG)
-                                LOG.debug("{} {} {}", this, wrapResult.getStatus(), BufferUtil.toDetailString(_encryptedOutput));
+                                LOG.debug("{} {} {}", this, wrapResultStatus, BufferUtil.toDetailString(_encryptedOutput));
+
+                            if (wrapResult.getHandshakeStatus() == HandshakeStatus.FINISHED && !_handshaken)
+                            {
+                                _handshaken = true;
+                                if (DEBUG)
+                                    LOG.debug("{} handshake completed server-side", SslConnection.this);
+                            }
+
+                            HandshakeStatus handshakeStatus = _sslEngine.getHandshakeStatus();
+
+                            // Check whether renegotiation is allowed
+                            if (_handshaken && handshakeStatus != HandshakeStatus.NOT_HANDSHAKING && !isRenegotiationAllowed())
+                            {
+                                if (DEBUG)
+                                    LOG.debug("{} renegotiation denied", SslConnection.this);
+                                shutdownOutput();
+                                return allConsumed;
+                            }
 
                             // if we have net bytes, let's try to flush them
                             if (BufferUtil.hasContent(_encryptedOutput))
                                 getEndPoint().flush(_encryptedOutput);
 
                             // But we also might have more to do for the handshaking state.
-                            switch (_sslEngine.getHandshakeStatus())
+                            switch (handshakeStatus)
                             {
                                 case NOT_HANDSHAKING:
                                     // Return with the number of bytes consumed (which may be 0)
-                                    return all_consumed&&BufferUtil.isEmpty(_encryptedOutput);
+                                    return allConsumed && BufferUtil.isEmpty(_encryptedOutput);
 
                                 case NEED_TASK:
                                     // run the task and continue
@@ -737,14 +791,13 @@
                                         _flushRequiresFillToProgress = true;
                                         fill(__FLUSH_CALLED_FILL);
                                         // Check if after the fill() we need to wrap again
-                                        if (_sslEngine.getHandshakeStatus() == HandshakeStatus.NEED_WRAP)
+                                        if (handshakeStatus == HandshakeStatus.NEED_WRAP)
                                             continue;
                                     }
-                                    return all_consumed&&BufferUtil.isEmpty(_encryptedOutput);
+                                    return allConsumed&&BufferUtil.isEmpty(_encryptedOutput);
 
                                 case FINISHED:
                                     throw new IllegalStateException();
-
                             }
                     }
                 }
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/SelectChannelEndPointSslTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/SelectChannelEndPointSslTest.java
index 6f956a1..77aea8b 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/SelectChannelEndPointSslTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/SelectChannelEndPointSslTest.java
@@ -74,10 +74,9 @@
         SSLEngine engine = __sslCtxFactory.newSSLEngine();
         engine.setUseClientMode(false);
         SslConnection sslConnection = new SslConnection(__byteBufferPool, _threadPool, endpoint, engine);
-
+        sslConnection.setRenegotiationAllowed(__sslCtxFactory.isRenegotiationAllowed());
         Connection appConnection = super.newConnection(channel,sslConnection.getDecryptedEndPoint());
         sslConnection.getDecryptedEndPoint().setConnection(appConnection);
-
         return sslConnection;
     }
 
diff --git a/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java b/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java
index 506d50b..c02bd00 100644
--- a/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java
+++ b/jetty-io/src/test/java/org/eclipse/jetty/io/SslConnectionTest.java
@@ -30,7 +30,6 @@
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
-
 import javax.net.ssl.SSLEngine;
 import javax.net.ssl.SSLSocket;
 
@@ -80,10 +79,9 @@
             SSLEngine engine = __sslCtxFactory.newSSLEngine();
             engine.setUseClientMode(false);
             SslConnection sslConnection = new SslConnection(__byteBufferPool, getExecutor(), endpoint, engine);
-
+            sslConnection.setRenegotiationAllowed(__sslCtxFactory.isRenegotiationAllowed());
             Connection appConnection = new TestConnection(sslConnection.getDecryptedEndPoint());
             sslConnection.getDecryptedEndPoint().setConnection(appConnection);
-
             return sslConnection;
         }
 
diff --git a/jetty-jaas/pom.xml b/jetty-jaas/pom.xml
index c90b92f..974d960 100644
--- a/jetty-jaas/pom.xml
+++ b/jetty-jaas/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-jaas</artifactId>
diff --git a/jetty-jaspi/pom.xml b/jetty-jaspi/pom.xml
index ab7f0bf..4ed1f95 100644
--- a/jetty-jaspi/pom.xml
+++ b/jetty-jaspi/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-jaspi</artifactId>
diff --git a/jetty-jmx/pom.xml b/jetty-jmx/pom.xml
index 45ee56c..dd2813f 100644
--- a/jetty-jmx/pom.xml
+++ b/jetty-jmx/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-jmx</artifactId>
diff --git a/jetty-jndi/pom.xml b/jetty-jndi/pom.xml
index 29f8774..e58d8f6 100644
--- a/jetty-jndi/pom.xml
+++ b/jetty-jndi/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-jndi</artifactId>
diff --git a/jetty-jsp/pom.xml b/jetty-jsp/pom.xml
index aa406a5..5fc0eb2 100644
--- a/jetty-jsp/pom.xml
+++ b/jetty-jsp/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-jsp</artifactId>
diff --git a/jetty-jspc-maven-plugin/pom.xml b/jetty-jspc-maven-plugin/pom.xml
index 59b3671..2d2ae6b 100644
--- a/jetty-jspc-maven-plugin/pom.xml
+++ b/jetty-jspc-maven-plugin/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-jspc-maven-plugin</artifactId>
diff --git a/jetty-maven-plugin/pom.xml b/jetty-maven-plugin/pom.xml
index c19c48f..1cc716c 100644
--- a/jetty-maven-plugin/pom.xml
+++ b/jetty-maven-plugin/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-maven-plugin</artifactId>
diff --git a/jetty-monitor/pom.xml b/jetty-monitor/pom.xml
index ee63fa2..2704f7e 100644
--- a/jetty-monitor/pom.xml
+++ b/jetty-monitor/pom.xml
@@ -19,7 +19,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-monitor</artifactId>
diff --git a/jetty-nosql/pom.xml b/jetty-nosql/pom.xml
index f395758..cf8ca80 100644
--- a/jetty-nosql/pom.xml
+++ b/jetty-nosql/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-nosql</artifactId>
diff --git a/jetty-npn/pom.xml b/jetty-npn/pom.xml
deleted file mode 100644
index 28d3ad1..0000000
--- a/jetty-npn/pom.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>org.eclipse.jetty</groupId>
-        <artifactId>jetty-project</artifactId>
-        <version>9.0.0-SNAPSHOT</version>
-    </parent>
-
-    <modelVersion>4.0.0</modelVersion>
-    <groupId>org.eclipse.jetty.npn</groupId>
-    <artifactId>npn-api</artifactId>
-    <version>1.1.1-SNAPSHOT</version>
-    <name>Jetty :: Next Protocol Negotiation :: API</name>
-
-    <properties>
-      <!-- for now we do make it an OSGi bundle...
-      but it needs to be in the bootstrap classes at runtime. -->
-        <bundle-symbolic-name>org.eclipse.jetty.npn</bundle-symbolic-name>
-    </properties>
-
-    <scm>
-      <connection>scm:git:http://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git</connection>
-      <developerConnection>scm:git:ssh://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git</developerConnection>
-       <url>http://git.eclipse.org/c/jetty/org.eclipse.jetty.project.git/tree/jetty-npn</url>
-    </scm>
-
-    <build>
-      <plugins>
-        <plugin>
-          <groupId>org.apache.felix</groupId>
-          <artifactId>maven-bundle-plugin</artifactId>
-          <extensions>true</extensions>
-          <executions>
-            <execution>
-              <goals>
-                <goal>manifest</goal>
-              </goals>
-              <configuration>
-                <instructions>
-                  <Export-Package>org.eclipse.jetty.npn.*;version="9.0"</Export-Package>
-                  <Import-Package>*</Import-Package>
-                  <Bundle-Description>Next Protocol Negotiation API. must be in the bootstrap packages at runtime.</Bundle-Description>
-                </instructions>
-              </configuration>
-             </execution>
-          </executions>
-        </plugin>
-      <plugin>
-        <!--
-        Required for OSGI
-        -->
-        <groupId>org.apache.maven.plugins</groupId>
-        <artifactId>maven-jar-plugin</artifactId>
-        <configuration>
-          <archive>
-            <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
-          </archive>
-        </configuration>
-      </plugin>
-      <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-release-plugin</artifactId>
-          <version>2.2.1</version>
-          <configuration>
-            <useReleaseProfile>false</useReleaseProfile>
-            <goals>deploy</goals>
-            <arguments>-Peclipse-release</arguments>
-            <preparationGoals>clean install</preparationGoals>
-          </configuration>
-        </plugin>
-      </plugins>
-    </build>
-</project>
diff --git a/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java b/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java
deleted file mode 100644
index 6dbea16..0000000
--- a/jetty-npn/src/main/java/org/eclipse/jetty/npn/NextProtoNego.java
+++ /dev/null
@@ -1,248 +0,0 @@
-//
-//  ========================================================================
-//  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.npn;
-
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.WeakHashMap;
-import javax.net.ssl.SSLEngine;
-import javax.net.ssl.SSLSocket;
-
-/**
- * <p>{@link NextProtoNego} provides an API to applications that want to make use of the
- * <a href="http://technotes.googlecode.com/git/nextprotoneg.html">Next Protocol Negotiation</a>.</p>
- * <p>The NPN extension is only available when using the TLS protocol, therefore applications must
- * ensure that the TLS protocol is used:</p>
- * <pre>
- * SSLContext context = SSLContext.getInstance("TLSv1");
- * </pre>
- * <p>Refer to the
- * <a href="http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#SSLContext">list
- * of standard SSLContext protocol names</a> for further information on TLS protocol versions supported.</p>
- * <p>Applications must register instances of either {@link SSLSocket} or {@link SSLEngine} with a
- * {@link ClientProvider} or with a {@link ServerProvider}, depending whether they are on client or
- * server side.</p>
- * <p>The NPN implementation will invoke the provider callbacks to allow applications to interact
- * with the negotiation of the next protocol.</p>
- * <p>Client side typical usage:</p>
- * <pre>
- * SSLSocket sslSocket = ...;
- * NextProtoNego.put(sslSocket, new NextProtoNego.ClientProvider()
- * {
- *     &#64;Override
- *     public boolean supports()
- *     {
- *         return true;
- *     }
- *
- *     &#64;Override
- *     public void unsupported()
- *     {
- *     }
- *
- *     &#64;Override
- *     public String selectProtocol(List&lt;String&gt; protocols)
- *     {
- *         return protocols.get(0);
- *     }
- *  });
- * </pre>
- * <p>Server side typical usage:</p>
- * <pre>
- * SSLSocket sslSocket = ...;
- * NextProtoNego.put(sslSocket, new NextProtoNego.ServerProvider()
- * {
- *     &#64;Override
- *     public void unsupported()
- *     {
- *     }
- *
- *     &#64;Override
- *     public List<String> protocols()
- *     {
- *         return Arrays.asList("http/1.1");
- *     }
- *
- *     &#64;Override
- *     public void protocolSelected(String protocol)
- *     {
- *         System.out.println("Protocol Selected is: " + protocol);
- *     }
- *  });
- * </pre>
- * <p>There is no need to unregister {@link SSLSocket} or {@link SSLEngine} instances, as they
- * are kept in a {@link WeakHashMap} and will be garbage collected when the application does not
- * hard reference them anymore. However, methods to explicitly unregister {@link SSLSocket} or
- * {@link SSLEngine} instances are provided.</p>
- * <p>In order to help application development, you can set the {@link NextProtoNego#debug} field
- * to {@code true} to have debug code printed to {@link System#err}.</p>
- */
-public class NextProtoNego
-{
-    /**
-     * <p>Enables debug logging on {@link System#err}.</p>
-     */
-    public static boolean debug = false;
-
-    private static Map<Object, Provider> objects = Collections.synchronizedMap(new WeakHashMap<Object, Provider>());
-
-    private NextProtoNego()
-    {
-    }
-
-    /**
-     * <p>Registers a SSLSocket with a provider.</p>
-     *
-     * @param socket the socket to register with the provider
-     * @param provider the provider to register with the socket
-     * @see #remove(SSLSocket)
-     */
-    public static void put(SSLSocket socket, Provider provider)
-    {
-        objects.put(socket, provider);
-    }
-
-    /**
-     * @param socket a socket registered with {@link #put(SSLSocket, Provider)}
-     * @return the provider registered with the given socket
-     */
-    public static Provider get(SSLSocket socket)
-    {
-        return objects.get(socket);
-    }
-
-    /**
-     * <p>Unregisters the given SSLSocket.</p>
-     *
-     * @param socket the socket to unregister
-     * @return the provider registered with the socket
-     * @see #put(SSLSocket, Provider)
-     */
-    public static Provider remove(SSLSocket socket)
-    {
-        return objects.remove(socket);
-    }
-
-    /**
-     * <p>Registers a SSLEngine with a provider.</p>
-     *
-     * @param engine the engine to register with the provider
-     * @param provider the provider to register with the engine
-     * @see #remove(SSLEngine)
-     */
-    public static void put(SSLEngine engine, Provider provider)
-    {
-        objects.put(engine, provider);
-    }
-
-    /**
-     *
-     * @param engine an engine registered with {@link #put(SSLEngine, Provider)}
-     * @return the provider registered with the given engine
-     */
-    public static Provider get(SSLEngine engine)
-    {
-        return objects.get(engine);
-    }
-
-    /**
-     * <p>Unregisters the given SSLEngine.</p>
-     *
-     * @param engine the engine to unregister
-     * @return the provider registered with the engine
-     * @see #put(SSLEngine, Provider)
-     */
-    public static Provider remove(SSLEngine engine)
-    {
-        return objects.remove(engine);
-    }
-
-    /**
-     * <p>Base, empty, interface for providers.</p>
-     */
-    public interface Provider
-    {
-    }
-
-    /**
-     * <p>The client-side provider interface that applications must implement to interact
-     * with the negotiation of the next protocol.</p>
-     */
-    public interface ClientProvider extends Provider
-    {
-        /**
-         * <p>Callback invoked to let the implementation know whether an
-         * empty NPN extension should be added to a ClientHello SSL message.</p>
-         *
-         * @return true to add the NPN extension, false otherwise
-         */
-        public boolean supports();
-
-        /**
-         * <p>Callback invoked to let the application know that the server does
-         * not support NPN.</p>
-         */
-        public void unsupported();
-
-        /**
-         * <p>Callback invoked to let the application select a protocol
-         * among the ones sent by the server.</p>
-         *
-         * @param protocols the protocols sent by the server
-         * @return the protocol selected by the application, or null if the
-         * NextProtocol SSL message should not be sent to the server
-         */
-        public String selectProtocol(List<String> protocols);
-    }
-
-    /**
-     * <p>The server-side provider interface that applications must implement to interact
-     * with the negotiation of the next protocol.</p>
-     */
-    public interface ServerProvider extends Provider
-    {
-        /**
-         * <p>Callback invoked to let the application know that the client does not
-         * support NPN.</p>
-         */
-        public void unsupported();
-
-        /**
-         * <p>Callback invoked to let the implementation know the list
-         * of protocols that should be added to an NPN extension in a
-         * ServerHello SSL message.</p>
-         * <p>This callback is invoked only if the client sent a NPN extension.</p>
-         *
-         * @return the list of protocols, or null if no NPN extension
-         * should be sent to the client
-         */
-        public List<String> protocols();
-
-        /**
-         * <p>Callback invoked to let the application know the protocol selected
-         * by the client.</p>
-         * <p>This callback is invoked only if the client sent a NextProtocol SSL message.</p>
-         *
-         * @param protocol the selected protocol
-         */
-        public void protocolSelected(String protocol);
-    }
-}
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
index 325448d..a7e5645 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot-jsp/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty.osgi</groupId>
     <artifactId>jetty-osgi-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-osgi-boot-jsp</artifactId>
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/ContainerTldBundleDiscoverer.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/ContainerTldBundleDiscoverer.java
new file mode 100644
index 0000000..f9c212a
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/ContainerTldBundleDiscoverer.java
@@ -0,0 +1,153 @@
+//
+//  ========================================================================
+//  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.osgi.boot.jasper;
+
+import java.io.File;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.regex.Pattern;
+
+import org.eclipse.jetty.deploy.DeploymentManager;
+import org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration;
+import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
+import org.eclipse.jetty.osgi.boot.utils.TldBundleDiscoverer;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.FrameworkUtil;
+
+
+
+/**
+ * ContainerTldBundleDiscoverer
+ * 
+ * 
+ * Use a System property to define bundles that contain tlds that need to
+ * be treated by jasper as if they were on the jetty container's classpath.
+ * 
+ * The value of the property is evaluated against the DeploymentManager 
+ * context attribute "org.eclipse.jetty.server.webapp.containerIncludeBundlePattern", 
+ * which defines a pattern of matching bundle names.
+ * 
+ * The bundle locations are converted to URLs for jasper's use.
+ * 
+ * Eg:
+ * -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet,com.opensymphony.module.sitemesh
+ * 
+ */
+public class ContainerTldBundleDiscoverer implements TldBundleDiscoverer
+{
+    /**
+     * Comma separated list of names of bundles that contain tld files that should be
+     * discoved by jasper as if they were on the container's classpath.
+     * Eg:
+     * -Djetty.osgi.tldbundles=org.springframework.web.servlet,com.opensymphony.module.sitemesh
+     */
+    public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles";
+
+
+
+    /**
+     * Check the System property "org.eclipse.jetty.osgi.tldbundles" for names of
+     * bundles that contain tlds and convert to URLs.
+     * 
+     * @return The location of the jars that contain tld files as URLs.
+     */
+    public URL[] getUrlsForBundlesWithTlds(DeploymentManager deploymentManager, BundleFileLocatorHelper locatorHelper) throws Exception
+    {
+        // naive way of finding those bundles.
+        // lots of assumptions: for example we assume a single version of each
+        // bundle that would contain tld files.
+        // this is probably good enough as those tlds are loaded system-wide on
+        // jetty.
+        // to do better than this we need to do it on a per webapp basis.
+        // probably using custom properties in the ContextHandler service
+        // and mirroring those in the MANIFEST.MF
+
+        Bundle[] bundles = FrameworkUtil.getBundle(ContainerTldBundleDiscoverer.class).getBundleContext().getBundles();
+        HashSet<URL> urls = new HashSet<URL>();
+        String tmp = System.getProperty(SYS_PROP_TLD_BUNDLES); //comma separated exact names
+        List<String> sysNames =   new ArrayList<String>();
+        if (tmp != null)
+        {
+            StringTokenizer tokenizer = new StringTokenizer(tmp, ", \n\r\t", false);
+            while (tokenizer.hasMoreTokens())
+                sysNames.add(tokenizer.nextToken());
+        }
+        tmp = (String) deploymentManager.getContextAttribute(OSGiWebInfConfiguration.CONTAINER_BUNDLE_PATTERN); //bundle name patterns
+        Pattern pattern = (tmp==null? null : Pattern.compile(tmp));
+        for (Bundle bundle : bundles)
+        {
+            if (sysNames.contains(bundle.getSymbolicName()))
+                convertBundleLocationToURL(locatorHelper, bundle, urls);
+           
+            if (pattern != null && pattern.matcher(bundle.getSymbolicName()).matches())
+                convertBundleLocationToURL(locatorHelper, bundle, urls);
+        }
+
+        return urls.toArray(new URL[urls.size()]);
+
+    }
+
+    /**
+     * Resolves a bundle that contains tld files as a URL. The URLs are
+     * used by jasper to discover the tld files.
+     * 
+     * Support only 2 types of packaging for the bundle: - the bundle is a jar
+     * (recommended for runtime.) - the bundle is a folder and contain jars in
+     * the root and/or in the lib folder (nice for PDE developement situations)
+     * Unsupported: the bundle is a jar that embeds more jars.
+     * 
+     * @param locatorHelper
+     * @param bundle
+     * @param urls
+     * @throws Exception
+     */
+    private void convertBundleLocationToURL(BundleFileLocatorHelper locatorHelper, Bundle bundle, Set<URL> urls) throws Exception
+    {
+        File jasperLocation = locatorHelper.getBundleInstallLocation(bundle);
+        if (jasperLocation.isDirectory())
+        {
+            for (File f : jasperLocation.listFiles())
+            {
+                if (f.getName().endsWith(".jar") && f.isFile())
+                {
+                    urls.add(f.toURI().toURL());
+                }
+                else if (f.isDirectory() && f.getName().equals("lib"))
+                {
+                    for (File f2 : jasperLocation.listFiles())
+                    {
+                        if (f2.getName().endsWith(".jar") && f2.isFile())
+                        {
+                            urls.add(f2.toURI().toURL());
+                        }
+                    }
+                }
+            }
+            urls.add(jasperLocation.toURI().toURL());
+        }
+        else
+        {
+            urls.add(jasperLocation.toURI().toURL());
+        }
+    }
+}
\ No newline at end of file
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/JSTLBundleDiscoverer.java
similarity index 94%
rename from jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java
rename to jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/JSTLBundleDiscoverer.java
index 7b744b9..23628c3 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/WebappRegistrationCustomizerImpl.java
+++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/JSTLBundleDiscoverer.java
@@ -34,7 +34,7 @@
 import org.eclipse.jetty.deploy.DeploymentManager;
 import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
 import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
-import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
+import org.eclipse.jetty.osgi.boot.utils.TldBundleDiscoverer;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.Logger;
 import org.osgi.framework.Bundle;
@@ -44,17 +44,20 @@
 import org.xml.sax.SAXException;
 
 /**
+ * 
+ * JSTLBundleDiscoverer
+ * 
  * Fix various shortcomings with the way jasper parses the tld files. Plugs the
  * JSTL tlds assuming that they are packaged with the bundle that contains the
  * JSTL classes.
  * <p>
  * Pluggable tlds at the server level are handled by
- * {@link PluggableWebAppRegistrationCustomizerImpl}.
+ * {@link ContainerTldBundleDiscoverer}.
  * </p>
  */
-public class WebappRegistrationCustomizerImpl implements WebappRegistrationCustomizer
+public class JSTLBundleDiscoverer implements TldBundleDiscoverer
 {
-    private static final Logger LOG = Log.getLogger(WebappRegistrationCustomizerImpl.class);
+    private static final Logger LOG = Log.getLogger(JSTLBundleDiscoverer.class);
     
 
     /**
@@ -83,7 +86,7 @@
      */
     private static String DEFAULT_JSP_FACTORY_IMPL_CLASS = "org.apache.jasper.runtime.JspFactoryImpl";
 
-    public WebappRegistrationCustomizerImpl()
+    public JSTLBundleDiscoverer()
     {
         fixupDtdResolution();
 
@@ -136,7 +139,7 @@
      * @return array of URLs
      * @throws Exception
      */
-    public URL[] getJarsWithTlds(DeploymentManager deployer, BundleFileLocatorHelper locatorHelper) throws Exception
+    public URL[] getUrlsForBundlesWithTlds(DeploymentManager deployer, BundleFileLocatorHelper locatorHelper) throws Exception
     {
 
         ArrayList<URL> urls = new ArrayList<URL>();
@@ -148,7 +151,7 @@
         // So we can look for this class using this bundle's classloader:
         try
         {
-            Class<?> jstlClass = WebappRegistrationCustomizerImpl.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS);
+            Class<?> jstlClass = JSTLBundleDiscoverer.class.getClassLoader().loadClass(DEFAULT_JSTL_BUNDLE_CLASS);
 
             classesToAddToTheTldBundles.add(jstlClass);
         }
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java
deleted file mode 100644
index 2521ed1..0000000
--- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jasper/PluggableWebAppRegistrationCustomizerImpl.java
+++ /dev/null
@@ -1,187 +0,0 @@
-//
-//  ========================================================================
-//  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.osgi.boot.jasper;
-
-import java.io.File;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.StringTokenizer;
-import java.util.regex.Pattern;
-
-import org.eclipse.jetty.deploy.DeploymentManager;
-import org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration;
-import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
-import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.FrameworkUtil;
-
-/**
- * Plug bundles that contains tld files so that jasper will discover them and
- * set them up in jetty.
- * 
- * For example:
- * -Dorg.eclipse.jetty.osgi.tldbundles=org.springframework.web.servlet
- * ,com.opensymphony.module.sitemesh Otherwise use an attribute to the
- * WebAppDeployer &lt;New
- * class="org.eclipse.jetty.deploy.providers.WebAppProvider"&gt; .... &lt;Set
- * name="tldBundles"&gt;&ltProperty name="org.eclipse.jetty.osgi.tldsbundles"
- * default="" /&gt;&lt;/Set&gt; &lt;New&gt;
- */
-public class PluggableWebAppRegistrationCustomizerImpl implements WebappRegistrationCustomizer
-{
-    /**
-     * To plug into jasper bundles that contain tld files please use a list of
-     * bundle's symbolic names:
-     * -Djetty.osgi.tldbundles=org.springframework.web.servlet
-     * ,com.opensymphony.module.sitemesh
-     */
-    public static final String SYS_PROP_TLD_BUNDLES = "org.eclipse.jetty.osgi.tldbundles";
-
-    /**
-     * Union of the tld bundles defined system wide and the one defines as an
-     * attribute of the AppProvider.
-     * 
-     * @param provider
-     * @return
-     */
-    private static Collection<String> getTldBundles(DeploymentManager deploymentManager)
-    {
-        String sysprop = System.getProperty(SYS_PROP_TLD_BUNDLES);
-        String att = (String) deploymentManager.getContextAttribute(OSGiWebInfConfiguration.CONTAINER_BUNDLE_PATTERN);
-        if (sysprop == null && att == null) { return Collections.emptySet(); }
-        if (att == null)
-        {
-            att = sysprop;
-        }
-        else if (sysprop != null)
-        {
-            att = att + "," + sysprop;
-        }
-
-        Collection<String> tldbundles = new HashSet<String>();
-        StringTokenizer tokenizer = new StringTokenizer(att, ", \n\r\t", false);
-        while (tokenizer.hasMoreTokens())
-        {
-            tldbundles.add(tokenizer.nextToken());
-        }
-        return tldbundles;
-    }
-
-    /**
-     * @return The location of the jars that contain tld files. Jasper will
-     *         discover them.
-     */
-    public URL[] getJarsWithTlds(DeploymentManager deploymentManager, BundleFileLocatorHelper locatorHelper) throws Exception
-    {
-        // naive way of finding those bundles.
-        // lots of assumptions: for example we assume a single version of each
-        // bundle that would contain tld files.
-        // this is probably good enough as those tlds are loaded system-wide on
-        // jetty.
-        // to do better than this we need to do it on a per webapp basis.
-        // probably using custom properties in the ContextHandler service
-        // and mirroring those in the MANIFEST.MF
-
-        Bundle[] bundles = FrameworkUtil.getBundle(PluggableWebAppRegistrationCustomizerImpl.class).getBundleContext().getBundles();
-        HashSet<URL> urls = new HashSet<URL>();
-        String tmp = System.getProperty(SYS_PROP_TLD_BUNDLES); //comma separated exact names
-        List<String> sysNames =   new ArrayList<String>();
-        if (tmp != null)
-        {
-            StringTokenizer tokenizer = new StringTokenizer(tmp, ", \n\r\t", false);
-            while (tokenizer.hasMoreTokens())
-                sysNames.add(tokenizer.nextToken());
-        }
-        tmp = (String) deploymentManager.getContextAttribute(OSGiWebInfConfiguration.CONTAINER_BUNDLE_PATTERN); //bundle name patterns
-        Pattern pattern = (tmp==null? null : Pattern.compile(tmp));
-        for (Bundle bundle : bundles)
-        {
-            if (sysNames.contains(bundle.getSymbolicName()))
-                registerTldBundle(locatorHelper, bundle, urls);
-           
-            if (pattern != null && pattern.matcher(bundle.getSymbolicName()).matches())
-                registerTldBundle(locatorHelper, bundle, urls);
-        }
-
-        return urls.toArray(new URL[urls.size()]);
-
-    }
-
-    /**
-     * Resolves the bundle that contains tld files as a set of URLs that will be
-     * passed to jasper as a URLClassLoader later on. Usually that would be a
-     * single URL per bundle. But we do some more work if there are jars
-     * embedded in the bundle.
-     * 
-     * The jasper TldScanner expects a URLClassloader to parse a jar for the
-     * /META-INF/*.tld it may contain. We place the bundles that we know contain
-     * such tag-libraries. Please note that it will work if and only if the
-     * bundle is a jar (!) Currently we just hardcode the bundle that contains
-     * the jstl implemenation.
-     * 
-     * A workaround when the tld cannot be parsed with this method is to copy
-     * and paste it inside the WEB-INF of the webapplication where it is used.
-     * 
-     * Support only 2 types of packaging for the bundle: - the bundle is a jar
-     * (recommended for runtime.) - the bundle is a folder and contain jars in
-     * the root and/or in the lib folder (nice for PDE developement situations)
-     * Unsupported: the bundle is a jar that embeds more jars.
-     * 
-     * @param locatorHelper
-     * @param bundle
-     * @param urls
-     * @throws Exception
-     */
-    private void registerTldBundle(BundleFileLocatorHelper locatorHelper, Bundle bundle, Set<URL> urls) throws Exception
-    {
-        File jasperLocation = locatorHelper.getBundleInstallLocation(bundle);
-        if (jasperLocation.isDirectory())
-        {
-            for (File f : jasperLocation.listFiles())
-            {
-                if (f.getName().endsWith(".jar") && f.isFile())
-                {
-                    urls.add(f.toURI().toURL());
-                }
-                else if (f.isDirectory() && f.getName().equals("lib"))
-                {
-                    for (File f2 : jasperLocation.listFiles())
-                    {
-                        if (f2.getName().endsWith(".jar") && f2.isFile())
-                        {
-                            urls.add(f2.toURI().toURL());
-                        }
-                    }
-                }
-            }
-            urls.add(jasperLocation.toURI().toURL());
-        }
-        else
-        {
-            urls.add(jasperLocation.toURI().toURL());
-        }
-
-    }
-
-}
\ No newline at end of file
diff --git a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java
index 9741d21..b172702 100644
--- a/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java
+++ b/jetty-osgi/jetty-osgi-boot-jsp/src/main/java/org/eclipse/jetty/osgi/boot/jsp/FragmentActivator.java
@@ -19,21 +19,26 @@
 package org.eclipse.jetty.osgi.boot.jsp;
 
 import org.eclipse.jetty.osgi.boot.BundleWebAppProvider;
-import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
-import org.eclipse.jetty.osgi.boot.jasper.PluggableWebAppRegistrationCustomizerImpl;
-import org.eclipse.jetty.osgi.boot.jasper.WebappRegistrationCustomizerImpl;
+import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
+import org.eclipse.jetty.osgi.boot.jasper.ContainerTldBundleDiscoverer;
+import org.eclipse.jetty.osgi.boot.jasper.JSTLBundleDiscoverer;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
 
 /**
- * Pseudo fragment activator. Called by the main org.eclipse.jetty.osgi.boot
- * bundle. Please note: this is not a real BundleActivator. Simply something
- * called back by the host bundle.
- * <p>
- * It must be placed in the org.eclipse.jetty.osgi.boot.jsp package: this is
- * because org.eclipse.jetty.osgi.boot.jsp is the symbolic-name of this
- * fragment. From that name, the PackageadminTracker will call this class. IN a
- * different package it won't be called.
+ * FragmentActivator
+ * 
+ * Sets up support for jsp. All relevant jsp jars must also be installed
+ * into the osgi environment.
+ *  <p>
+ * Note that as this is part of a bundle fragment, this activator is NOT
+ * called by the OSGi environment. Instead, the org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminTracker
+ * simulates fragment activation and causes this class's start() method to
+ * be called.
+ * </p>
+ *  <p>
+ * The package of this class MUST match the Bundle-SymbolicName of this fragment
+ * in order for the PackageAdminTracker to find it.
  * </p>
  */
 public class FragmentActivator implements BundleActivator
@@ -43,12 +48,14 @@
      */
     public void start(BundleContext context) throws Exception
     {
+        //jsr199 compilation does not work in osgi
         System.setProperty("org.apache.jasper.compiler.disablejsr199", Boolean.TRUE.toString());
-        WebBundleTrackerCustomizer.JSP_REGISTRATION_HELPERS.add(new WebappRegistrationCustomizerImpl());
-        WebBundleTrackerCustomizer.JSP_REGISTRATION_HELPERS.add(new PluggableWebAppRegistrationCustomizerImpl());
-        //Put in the support for the tag libs
-        addTagLibSupport();
-      
+        
+        //set up some classes that will look for bundles with tlds that must be converted
+        //to urls and treated as if they are on the Jetty container's classpath so that 
+        //jasper can deal with them
+        ServerInstanceWrapper.addContainerTldBundleDiscoverer(new JSTLBundleDiscoverer());
+        ServerInstanceWrapper.addContainerTldBundleDiscoverer(new ContainerTldBundleDiscoverer());      
     }
 
     /**
@@ -58,12 +65,4 @@
     {
 
     }
-    
-    public void addTagLibSupport ()
-    {
-        String[] defaultConfigurations = new String[BundleWebAppProvider.getDefaultConfigurations().length+1];
-        System.arraycopy(BundleWebAppProvider.getDefaultConfigurations(), 0, defaultConfigurations, 0, BundleWebAppProvider.getDefaultConfigurations().length);
-        defaultConfigurations[defaultConfigurations.length-1] = "org.eclipse.jetty.osgi.boot.jsp.TagLibOSGiConfiguration";
-        BundleWebAppProvider.setDefaultConfigurations(defaultConfigurations);
-    }
 }
diff --git a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
index 59ce3cc..5927ad5 100644
--- a/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot-warurl/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty.osgi</groupId>
     <artifactId>jetty-osgi-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-osgi/jetty-osgi-boot/pom.xml b/jetty-osgi/jetty-osgi-boot/pom.xml
index 703ca92..a630b1f 100644
--- a/jetty-osgi/jetty-osgi-boot/pom.xml
+++ b/jetty-osgi/jetty-osgi-boot/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty.osgi</groupId>
     <artifactId>jetty-osgi-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-osgi-boot</artifactId>
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractContextProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractContextProvider.java
index 6f07480..5d801c6 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractContextProvider.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractContextProvider.java
@@ -22,14 +22,12 @@
 import java.net.URL;
 import java.util.Dictionary;
 import java.util.HashMap;
-import java.util.Hashtable;
 
 import org.eclipse.jetty.deploy.App;
 import org.eclipse.jetty.deploy.AppProvider;
 import org.eclipse.jetty.deploy.DeploymentManager;
 import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
 import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
-import org.eclipse.jetty.osgi.boot.utils.EventSender;
 import org.eclipse.jetty.osgi.boot.utils.OSGiClassLoader;
 import org.eclipse.jetty.server.handler.ContextHandler;
 import org.eclipse.jetty.util.component.AbstractLifeCycle;
@@ -37,11 +35,8 @@
 import org.eclipse.jetty.util.log.Logger;
 import org.eclipse.jetty.util.resource.JarResource;
 import org.eclipse.jetty.util.resource.Resource;
-import org.eclipse.jetty.webapp.WebAppContext;
 import org.eclipse.jetty.xml.XmlConfiguration;
 import org.osgi.framework.Bundle;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceRegistration;
 
 
 
@@ -49,14 +44,15 @@
 /**
  * AbstractContextProvider
  *
- *
+ * Base class for DeploymentManager Providers that can deploy ContextHandlers into 
+ * Jetty that have been discovered via OSGI either as bundles or services.
+ * 
  */
 public abstract class AbstractContextProvider extends AbstractLifeCycle implements AppProvider
 {
     private static final Logger LOG = Log.getLogger(AbstractContextProvider.class);
     
-    private DeploymentManager _deploymentManager;
-    
+    private DeploymentManager _deploymentManager;    
     
     private ServerInstanceWrapper _serverWrapper;
     
@@ -65,7 +61,7 @@
     
     /* ------------------------------------------------------------ */
     /**
-     * BundleApp
+     * OSGiApp
      *
      *
      */
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractOSGiApp.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractOSGiApp.java
index be09d2c..b9e040b 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractOSGiApp.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractOSGiApp.java
@@ -32,9 +32,10 @@
 
 
 /**
- * AbstractBundleApp
+ * AbstractOSGiApp
  *
- *
+ * Base class representing info about a webapp/ContextHandler that is deployed into Jetty.
+ * 
  */
 public abstract class AbstractOSGiApp extends App
 {      
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java
index 73da20f..cbae1c9 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/AbstractWebAppProvider.java
@@ -20,14 +20,9 @@
 
 import java.io.File;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Map;
-
 
 import org.eclipse.jetty.deploy.App;
 import org.eclipse.jetty.deploy.AppProvider;
@@ -35,7 +30,6 @@
 import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
 import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
 import org.eclipse.jetty.osgi.boot.internal.webapp.OSGiWebappClassLoader;
-import org.eclipse.jetty.osgi.boot.utils.EventSender;
 import org.eclipse.jetty.server.handler.ContextHandler;
 import org.eclipse.jetty.util.component.AbstractLifeCycle;
 import org.eclipse.jetty.util.log.Log;
@@ -44,9 +38,7 @@
 import org.eclipse.jetty.xml.XmlConfiguration;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.packageadmin.PackageAdmin;
 
 
@@ -55,7 +47,9 @@
 /**
  * AbstractWebAppProvider
  *
- *
+ * Base class for Jetty DeploymentManager Providers that are capable of deploying a webapp,
+ * either from a bundle or an OSGi service.
+ * 
  */
 public abstract class AbstractWebAppProvider extends AbstractLifeCycle implements AppProvider
 {
@@ -64,10 +58,9 @@
     public static String __defaultConfigurations[] = {
                                                             "org.eclipse.jetty.osgi.boot.OSGiWebInfConfiguration",
                                                             "org.eclipse.jetty.webapp.WebXmlConfiguration",
-                                                            "org.eclipse.jetty.osgi.boot.OSGiMetaInfConfiguration",
+                                                            "org.eclipse.jetty.webapp.MetaInfConfiguration",
                                                             "org.eclipse.jetty.webapp.FragmentConfiguration",
-                                                            "org.eclipse.jetty.webapp.JettyWebXmlConfiguration"//,
-                                                            //"org.eclipse.jetty.osgi.boot.jsp.TagLibOSGiConfiguration"                            
+                                                            "org.eclipse.jetty.webapp.JettyWebXmlConfiguration"                          
                                                      };
     
     public static void setDefaultConfigurations (String[] defaultConfigs)
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleContextProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleContextProvider.java
index 149aa99..92dcbd4 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleContextProvider.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleContextProvider.java
@@ -26,16 +26,11 @@
 import java.util.Map;
 
 import org.eclipse.jetty.deploy.App;
-import org.eclipse.jetty.deploy.DeploymentManager;
 import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
-import org.eclipse.jetty.osgi.boot.utils.EventSender;
-import org.eclipse.jetty.server.handler.ContextHandler;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.jetty.webapp.WebAppContext;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 
 
@@ -43,7 +38,7 @@
 /**
  * BundleContextProvider
  *
- * Handles deploying bundles that define a context xml file for configuring them.
+ * Handles deploying OSGi bundles that define a context xml file for configuring them.
  * 
  *
  */
@@ -136,6 +131,7 @@
             }
             apps.add(app);
             getDeploymentManager().addApp(app);
+            added = true;
         }
 
         return added; //true if even 1 context from this bundle was added
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleProvider.java
index c87c071..e137269 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleProvider.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleProvider.java
@@ -20,6 +20,11 @@
 
 import org.osgi.framework.Bundle;
 
+/**
+ * BundleProvider
+ *
+ * Jetty DeploymentManager Provider api for webapps or ContextHandlers that are discovered as osgi bundles.
+ */
 public interface BundleProvider
 {
     public boolean bundleAdded (Bundle bundle) throws Exception;
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleWebAppProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleWebAppProvider.java
index 2a5e6e3..ab38f29 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleWebAppProvider.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/BundleWebAppProvider.java
@@ -25,7 +25,6 @@
 
 import org.eclipse.jetty.deploy.App;
 import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
-import org.eclipse.jetty.osgi.boot.utils.EventSender;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.Logger;
 import org.osgi.framework.Bundle;
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java
index 2ed6e7b..8763ece 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/JettyBootstrapActivator.java
@@ -18,45 +18,35 @@
 
 package org.eclipse.jetty.osgi.boot;
 
-import java.util.Dictionary;
-import java.util.Hashtable;
-
 import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper;
 import org.eclipse.jetty.osgi.boot.internal.serverfactory.JettyServerServiceTracker;
-import org.eclipse.jetty.osgi.boot.internal.webapp.IWebBundleDeployerHelper;
-import org.eclipse.jetty.osgi.boot.internal.webapp.JettyContextHandlerServiceTracker;
-import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
+import org.eclipse.jetty.osgi.boot.internal.webapp.BundleWatcher;
+import org.eclipse.jetty.osgi.boot.internal.webapp.ServiceWatcher;
 import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.webapp.WebAppContext;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleException;
-import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.util.tracker.BundleTracker;
 
 /**
+ * JettyBootstrapActivator
+ * 
  * Bootstrap jetty and publish a default Server instance as an OSGi service.
  * 
  * Listen for other Server instances to be published as services and support them as deployment targets.
  * 
- * Listen for Bundles to be activated, and deploy those that represent webapps to one of the known Server instances.
+ * Listen for Bundles to be activated, and deploy those that represent webapps/ContextHandlers to one of the known Server instances.
  * 
- * <ol>
- * <li>basic servlet [ok]</li>
- * <li>basic jetty.xml [ok]</li>
- * <li>basic jetty.xml and jetty-plus.xml [ok]</li>
- * <li>basic jsp [ok]</li>
- * <li>jsp with tag-libs [ok]</li>
- * <li>test-jndi with atomikos and derby inside ${jetty.home}/lib/ext [ok]</li>
- * </ul>
  */
 public class JettyBootstrapActivator implements BundleActivator
 {
-
+    private static final Logger LOG = Log.getLogger(JettyBootstrapActivator.class);
+    
     private static JettyBootstrapActivator INSTANCE = null;
 
     public static JettyBootstrapActivator getInstance()
@@ -66,7 +56,7 @@
 
     private ServiceRegistration _registeredServer;
 
-    private JettyContextHandlerServiceTracker _jettyContextHandlerTracker;
+    private ServiceWatcher _jettyContextHandlerTracker;
 
     private PackageAdminServiceTracker _packageAdminServiceTracker;
 
@@ -75,7 +65,10 @@
     private BundleContext _bundleContext;
 
     private JettyServerServiceTracker _jettyServerServiceTracker;
-
+    
+    
+    
+    /* ------------------------------------------------------------ */
     /**
      * Setup a new jetty Server, registers it as a service. Setup the Service
      * tracker for the jetty ContextHandlers that are in charge of deploying the
@@ -84,7 +77,7 @@
      * 
      * @param context
      */
-    public void start(BundleContext context) throws Exception
+    public void start(final BundleContext context) throws Exception
     {
         INSTANCE = this;
         _bundleContext = context;
@@ -98,18 +91,23 @@
         context.addServiceListener(_jettyServerServiceTracker, "(objectclass=" + Server.class.getName() + ")");
 
         // track ContextHandler class instances and deploy them to one of the known Servers
-        _jettyContextHandlerTracker = new JettyContextHandlerServiceTracker();
+        _jettyContextHandlerTracker = new ServiceWatcher();
         context.addServiceListener(_jettyContextHandlerTracker, "(objectclass=" + ContextHandler.class.getName() + ")");
 
         // Create a default jetty instance right now.
-        DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context);
+        Server defaultServer = DefaultJettyAtJettyHomeHelper.startJettyAtJettyHome(context);
 
-        // track Bundles and deploy those that represent webapps to one of the known Servers
-        WebBundleTrackerCustomizer customizer = new WebBundleTrackerCustomizer();
-        _webBundleTracker = new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, customizer);
-        customizer.setAndOpenWebBundleTracker(_webBundleTracker);
+        //Create a bundle tracker to help deploy webapps and ContextHandlers
+        BundleWatcher bundleTrackerCustomizer = new BundleWatcher();
+        bundleTrackerCustomizer.setWaitForDefaultServer(defaultServer != null);
+        _webBundleTracker =  new BundleTracker(context, Bundle.ACTIVE | Bundle.STOPPING, bundleTrackerCustomizer);
+        bundleTrackerCustomizer.setBundleTracker(_webBundleTracker);
+        bundleTrackerCustomizer.open();
     }
-
+    
+    
+    
+    /* ------------------------------------------------------------ */
     /**
      * Stop the activator.
      * 
@@ -120,7 +118,6 @@
     {
         try
         {
-
             if (_webBundleTracker != null)
             {
                 _webBundleTracker.close();
@@ -164,122 +161,4 @@
             INSTANCE = null;
         }
     }
-
-    /**
-     * Helper method that creates a new org.jetty.webapp.WebAppContext and
-     * registers it as an OSGi service. The tracker
-     * {@link JettyContextHandlerServiceTracker} will do the actual deployment.
-     * 
-     * @param contributor The bundle
-     * @param webappFolderPath The path to the root of the webapp. Must be a
-     *            path relative to bundle; either an absolute path.
-     * @param contextPath The context path. Must start with "/"
-     * @throws Exception
-     */
-    public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath) throws Exception
-    {
-        checkBundleActivated();
-        WebAppContext contextHandler = new WebAppContext();
-        Dictionary<String,String> dic = new Hashtable<String,String>();
-        dic.put(OSGiWebappConstants.SERVICE_PROP_WAR, webappFolderPath);
-        dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH, contextPath);
-        String requireTldBundle = (String) contributor.getHeaders().get(OSGiWebappConstants.REQUIRE_TLD_BUNDLE);
-        if (requireTldBundle != null)
-        {
-            dic.put(OSGiWebappConstants.SERVICE_PROP_REQUIRE_TLD_BUNDLE, requireTldBundle);
-        }
-        contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic);
-    }
-
-    /**
-     * Helper method that creates a new org.jetty.webapp.WebAppContext and
-     * registers it as an OSGi service. The tracker
-     * {@link JettyContextHandlerServiceTracker} will do the actual deployment.
-     * 
-     * @param contributor The bundle
-     * @param webappFolderPath The path to the root of the webapp. Must be a
-     *            path relative to bundle; either an absolute path.
-     * @param contextPath The context path. Must start with "/"
-     * @param dic TODO: parameter description
-     * @throws Exception
-     */
-    public static void registerWebapplication(Bundle contributor, String webappFolderPath, String contextPath, Dictionary<String, String> dic) throws Exception
-    {
-        checkBundleActivated();
-        WebAppContext contextHandler = new WebAppContext();
-        dic.put(OSGiWebappConstants.SERVICE_PROP_WAR, webappFolderPath);
-        dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_PATH, contextPath);
-        contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic);
-    }
-
-    /**
-     * Helper method that creates a new skeleton of a ContextHandler and
-     * registers it as an OSGi service. The tracker
-     * {@link JettyContextHandlerServiceTracker} will do the actual deployment.
-     * 
-     * @param contributor The bundle that registers a new context
-     * @param contextFilePath The path to the file inside the bundle that
-     *            defines the context.
-     * @throws Exception
-     */
-    public static void registerContext(Bundle contributor, String contextFilePath) throws Exception
-    {
-        registerContext(contributor, contextFilePath, new Hashtable<String, String>());
-    }
-
-    /**
-     * Helper method that creates a new skeleton of a ContextHandler and
-     * registers it as an OSGi service. The tracker
-     * {@link JettyContextHandlerServiceTracker} will do the actual deployment.
-     * 
-     * @param contributor The bundle that registers a new context
-     * @param contextFilePath The path to the file inside the bundle that
-     *            defines the context.
-     * @param dic TODO: parameter description
-     * @throws Exception
-     */
-    public static void registerContext(Bundle contributor, String contextFilePath, Dictionary<String, String> dic) throws Exception
-    {
-        checkBundleActivated();
-        ContextHandler contextHandler = new ContextHandler();
-        dic.put(OSGiWebappConstants.SERVICE_PROP_CONTEXT_FILE_PATH, contextFilePath);
-        dic.put(IWebBundleDeployerHelper.INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE, Boolean.TRUE.toString());
-        contributor.getBundleContext().registerService(ContextHandler.class.getName(), contextHandler, dic);
-    }
-
-    public static void unregister(String contextPath)
-    {
-        // todo
-    }
-
-    /**
-     * Since org.eclipse.jetty.osgi.boot does not have a lazy activation policy
-     * when one of the static methods to register a webapp is called we should
-     * make sure that the bundle is started.
-     */
-    private static void checkBundleActivated()
-    {
-        if (INSTANCE == null)
-        {
-            Bundle thisBundle = FrameworkUtil.getBundle(JettyBootstrapActivator.class);
-            try
-            {
-                thisBundle.start();
-            }
-            catch (BundleException e)
-            {
-                // nevermind.
-            }
-        }
-    }
-
-    /**
-     * @return The bundle context for this bundle.
-     */
-    public static BundleContext getBundleContext()
-    {
-        checkBundleActivated();
-        return INSTANCE._bundleContext;
-    }
-
 }
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiDeployer.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiDeployer.java
index 5f9321e..1b80e04 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiDeployer.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiDeployer.java
@@ -27,7 +27,9 @@
 /**
  * OSGiDeployer
  *
- *
+ * Extension of standard Jetty deployer that emits OSGi EventAdmin 
+ * events whenever a webapp is deployed into OSGi via Jetty.
+ * 
  */
 public class OSGiDeployer extends StandardDeployer
 {
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
index bacc8ea..9767bd3 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiMetaInfConfiguration.java
@@ -32,6 +32,14 @@
 import org.eclipse.jetty.webapp.WebAppContext;
 import org.osgi.framework.Bundle;
 
+/**
+ * OSGiMetaInfConfiguration
+ *
+ * Extension of standard Jetty MetaInfConfiguration class to handle OSGi bundle
+ * fragments that may also need to be scanned for META-INF info.
+ * 
+ * @deprecated
+ */
 public class OSGiMetaInfConfiguration extends MetaInfConfiguration
 {
     private static final Logger LOG = Log.getLogger(OSGiMetaInfConfiguration.class);
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiServerConstants.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiServerConstants.java
index 2f9df55..67ef323 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiServerConstants.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiServerConstants.java
@@ -19,6 +19,8 @@
 package org.eclipse.jetty.osgi.boot;
 
 /**
+ * OSGiServerConstants
+ * 
  * Name of the properties that configure a jetty Server OSGi service.
  */
 public class OSGiServerConstants
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiUndeployer.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiUndeployer.java
index ac06874..674f960 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiUndeployer.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiUndeployer.java
@@ -29,7 +29,9 @@
 /**
  * OSGiUndeployer
  *
- *
+ * Extension of the Jetty Undeployer which emits OSGi EventAdmin events
+ * whenever a webapp is undeployed from Jetty.
+ * 
  */
 public class OSGiUndeployer extends StandardUndeployer
 {
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
index 988ebb2..76eb8ad 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebInfConfiguration.java
@@ -52,7 +52,7 @@
     
     public static final String CONTAINER_BUNDLE_PATTERN = "org.eclipse.jetty.server.webapp.containerIncludeBundlePattern";
     
-    
+    /* ------------------------------------------------------------ */
     /** 
      * Check to see if there have been any bundle symbolic names added of bundles that should be
      * regarded as being on the container classpath, and scanned for fragments, tlds etc etc.
@@ -120,7 +120,7 @@
     }
     
     
-    
+    /* ------------------------------------------------------------ */
     /** 
      * Consider the fragment bundles associated with the bundle of the webapp being deployed.
      * 
@@ -148,7 +148,7 @@
         return mergedResources;
     }
     
-    
+    /* ------------------------------------------------------------ */
     /** 
      * Allow fragments to supply some resources that are added to the baseResource of the webapp.
      * 
@@ -227,11 +227,10 @@
             resources[resources.length-1] = context.getBaseResource();
             context.setBaseResource(new ResourceCollection(resources));
         }
-        
     }
 
     
-    
+    /* ------------------------------------------------------------ */
     /**
     * Resolves the bundle. Usually that would be a single URL per bundle. But we do some more work if there are jars
     * embedded in the bundle.
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebappConstants.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebappConstants.java
index 1908eb2..e97457a 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebappConstants.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/OSGiWebappConstants.java
@@ -19,7 +19,12 @@
 package org.eclipse.jetty.osgi.boot;
 
 /**
- * Name of the service properties for a ContextHandler that configure a webapp deployed on jetty OSGi.
+ * OSGiWebappConstants
+ * 
+ * 
+ * Constants (MANIFEST headers, service properties etc) associated with deploying
+ * webapps into OSGi via Jetty.
+ * 
  */
 public class OSGiWebappConstants
 {
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceContextProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceContextProvider.java
index 2e36904..a228a62 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceContextProvider.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceContextProvider.java
@@ -38,7 +38,9 @@
 /**
  * ServiceContextProvider
  *
- *
+ * Jetty DeploymentManager Provider that is able to deploy ContextHandlers discovered via OSGi as services.
+ * 
+ * 
  */
 public class ServiceContextProvider extends AbstractContextProvider implements ServiceProvider
 { 
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceProvider.java
index f2304c6..34335cf 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceProvider.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceProvider.java
@@ -21,6 +21,11 @@
 import org.eclipse.jetty.server.handler.ContextHandler;
 import org.osgi.framework.ServiceReference;
 
+/**
+ * ServiceProvider
+ *
+ * Jetty DeploymentManager Provider api for webapps or ContextHandlers that are discovered as OSGi services.
+ */
 public interface ServiceProvider
 {
     public boolean serviceAdded (ServiceReference ref, ContextHandler handler) throws Exception;
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceWebAppProvider.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceWebAppProvider.java
index e3f97f0..6008aa0 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceWebAppProvider.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/ServiceWebAppProvider.java
@@ -27,7 +27,6 @@
 import org.eclipse.jetty.deploy.AppProvider;
 import org.eclipse.jetty.deploy.DeploymentManager;
 import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
-import org.eclipse.jetty.osgi.boot.utils.EventSender;
 import org.eclipse.jetty.server.handler.ContextHandler;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.Logger;
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloader.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloader.java
deleted file mode 100644
index 4b48aef..0000000
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloader.java
+++ /dev/null
@@ -1,65 +0,0 @@
-//
-//  ========================================================================
-//  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.osgi.boot.internal.jsp;
-
-import java.net.URL;
-import java.net.URLClassLoader;
-
-/**
- * Tricky url classloader. In fact we don't want a real URLClassLoader: we want
- * OSGi to provide its classloader and let it does. But to let
- * {@link org.apache.jasper.compiler.TldLocationsCache} find the core tlds
- * inside the jars we must be a URLClassLoader that returns an array of jars
- * where tlds are stored when the method getURLs is called.
- */
-public class TldLocatableURLClassloader extends URLClassLoader
-{
-
-    private URL[] _jarsWithTldsInside;
-
-    public TldLocatableURLClassloader(ClassLoader osgiClassLoader, URL[] jarsWithTldsInside)
-    {
-        super(new URL[] {},osgiClassLoader);
-        _jarsWithTldsInside = jarsWithTldsInside;
-    }
-
-    /**
-     * @return the jars that contains tlds so that TldLocationsCache or
-     *         TldScanner can find them.
-     */
-    @Override
-    public URL[] getURLs()
-    {
-        return _jarsWithTldsInside;
-    }
-
-    public String toString()
-    {
-        StringBuilder builder = new StringBuilder();
-
-        if (_jarsWithTldsInside != null)
-        {
-            for (URL u:_jarsWithTldsInside)
-                builder.append(" "+u.toString());
-            return builder.toString();
-        }
-        else
-            return super.toString();
-    }
-}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloaderWithInsertedJettyClassloader.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloaderWithInsertedJettyClassloader.java
deleted file mode 100644
index e4cf805..0000000
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/jsp/TldLocatableURLClassloaderWithInsertedJettyClassloader.java
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-//  ========================================================================
-//  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.osgi.boot.internal.jsp;
-
-import java.net.URL;
-
-/**
- * Add a classloader to the
- * org.apache.jasper.compiler.TldLocatableURLClassloader. Hopefuly not
- * necessary: still experimenting.
- * 
- * @see TldLocatableURLClassloader
- */
-public class TldLocatableURLClassloaderWithInsertedJettyClassloader extends TldLocatableURLClassloader
-{
-
-    private ClassLoader _internalClassLoader;
-
-    /**
-     * 
-     * @param osgiClassLoaderParent
-     *            The parent classloader
-     * @param internalClassLoader
-     *            The classloader that will be at the same level than the
-     *            jarsWithTldsInside
-     * @param jarsWithTldsInside
-     *            jars that are scanned for tld files.
-     */
-    public TldLocatableURLClassloaderWithInsertedJettyClassloader(ClassLoader osgiClassLoaderParent, ClassLoader internalClassLoader, URL[] jarsWithTldsInside)
-    {
-        super(osgiClassLoaderParent,jarsWithTldsInside);
-        _internalClassLoader = internalClassLoader;
-    }
-
-    protected Class<?> findClass(String name) throws ClassNotFoundException
-    {
-        try
-        {
-            return super.findClass(name);
-        }
-        catch (ClassNotFoundException cne)
-        {
-            if (_internalClassLoader != null)
-            {
-                return _internalClassLoader.loadClass(name);
-            }
-            else
-            {
-                throw cne;
-            }
-        }
-    }
-}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java
index bef4dcf..a89ff5b 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/DefaultJettyAtJettyHomeHelper.java
@@ -29,7 +29,6 @@
 import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
 import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
 import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
-import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.Logger;
@@ -40,9 +39,12 @@
  * DefaultJettyAtJettyHomeHelper
  * 
  * 
+ * Creates a default instance of Jetty, based on the values of the
+ * System properties "jetty.home" or "jetty.home.bundle", one of which
+ * must be specified in order to create the default instance.
+ * 
  * Called by the {@link JettyBootstrapActivator} during the starting of the
- * bundle. If the system property 'jetty.home' is defined and points to a
- * folder, then setup the corresponding jetty server.
+ * bundle. 
  */
 public class DefaultJettyAtJettyHomeHelper
 {
@@ -64,6 +66,7 @@
     public static final String DEFAULT_JETTYHOME = "/jettyhome/";
     
     
+    
     /* ------------------------------------------------------------ */
     /**
      * Called by the JettyBootStrapActivator. If the system property jetty.home
@@ -87,7 +90,7 @@
      * as part of their properties.
      * </p>
      */
-    public static void startJettyAtJettyHome(BundleContext bundleContext) throws Exception
+    public static Server startJettyAtJettyHome(BundleContext bundleContext) throws Exception
     {
         String jettyHomeSysProp = System.getProperty(OSGiServerConstants.JETTY_HOME);
         String jettyHomeBundleSysProp = System.getProperty(OSGiServerConstants.JETTY_HOME_BUNDLE);
@@ -109,7 +112,7 @@
             if (!jettyHome.exists() || !jettyHome.isDirectory())
             {
                 LOG.warn("Unable to locate the jetty.home folder " + jettyHomeSysProp);
-                return;
+                return null;
             }
         }
         else if (jettyHomeBundleSysProp != null)
@@ -126,14 +129,14 @@
             if (jettyHomeBundle == null)
             {
                 LOG.warn("Unable to find the jetty.home.bundle named " + jettyHomeSysProp);
-                return;
+                return null;
             }
 
         }
         if (jettyHome == null && jettyHomeBundle == null)
         {
             LOG.warn("No default jetty created.");
-            return;
+            return null;
         }
 
         Server server = new Server();
@@ -152,8 +155,11 @@
         setProperty(properties, OSGiServerConstants.JETTY_PORT, System.getProperty(OSGiServerConstants.JETTY_PORT));
         setProperty(properties, OSGiServerConstants.JETTY_PORT_SSL, System.getProperty(OSGiServerConstants.JETTY_PORT_SSL));
 
-        //register the Server instance as an OSGi service.
+        //Register the default Server instance as an OSGi service.
+        //The JettyServerServiceTracker will notice it and configure it.
         bundleContext.registerService(Server.class.getName(), server, properties);
+        
+        return server;
     }
     
     
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/JettyServerServiceTracker.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/JettyServerServiceTracker.java
index e172c75..b946cd8 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/JettyServerServiceTracker.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/JettyServerServiceTracker.java
@@ -32,8 +32,11 @@
 import org.osgi.framework.ServiceReference;
 
 /**
- * Deploy the jetty server instances when they are registered as an OSGi
- * service.
+ * JettyServerServiceTracker
+ * 
+ * Tracks instances of Jetty Servers, and configures them so that they can deploy 
+ * webapps or ContextHandlers discovered from the OSGi environment.
+ * 
  */
 public class JettyServerServiceTracker implements ServiceListener, IManagedJettyServerRegistry
 {
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/ServerInstanceWrapper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/ServerInstanceWrapper.java
index a7e9daa..209fee6 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/ServerInstanceWrapper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/serverfactory/ServerInstanceWrapper.java
@@ -19,7 +19,6 @@
 package org.eclipse.jetty.osgi.boot.internal.serverfactory;
 
 import java.io.File;
-import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.ArrayList;
@@ -27,8 +26,10 @@
 import java.util.Dictionary;
 import java.util.Enumeration;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.StringTokenizer;
 
 import org.eclipse.jetty.deploy.AppLifeCycle;
@@ -44,11 +45,10 @@
 import org.eclipse.jetty.osgi.boot.OSGiUndeployer;
 import org.eclipse.jetty.osgi.boot.ServiceContextProvider;
 import org.eclipse.jetty.osgi.boot.ServiceWebAppProvider;
-import org.eclipse.jetty.osgi.boot.internal.jsp.TldLocatableURLClassloader;
 import org.eclipse.jetty.osgi.boot.internal.webapp.BundleFileLocatorHelperFactory;
 import org.eclipse.jetty.osgi.boot.internal.webapp.LibExtClassLoaderHelper;
-import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
-import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
+import org.eclipse.jetty.osgi.boot.utils.FakeURLClassLoader;
+import org.eclipse.jetty.osgi.boot.utils.TldBundleDiscoverer;
 import org.eclipse.jetty.server.Server;
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
 import org.eclipse.jetty.util.IO;
@@ -72,6 +72,9 @@
      * support the case where the bundle is zipped.
      */
     public static final String PROPERTY_THIS_JETTY_XML_FOLDER_URL = "this.jetty.xml.parent.folder.url";
+    
+    
+    private static Collection<TldBundleDiscoverer> __containerTldBundleDiscoverers = new ArrayList<TldBundleDiscoverer>();
 
     private static Logger LOG = Log.getLogger(ServerInstanceWrapper.class.getName());
     
@@ -96,6 +99,21 @@
     private DeploymentManager _deploymentManager;
     
     
+    
+    /* ------------------------------------------------------------ */
+    public static void addContainerTldBundleDiscoverer (TldBundleDiscoverer tldBundleDiscoverer)
+    {
+        __containerTldBundleDiscoverers.add(tldBundleDiscoverer);
+    }
+    
+    /* ------------------------------------------------------------ */
+    public static Collection<TldBundleDiscoverer> getContainerTldBundleDiscoverers()
+    {
+        return __containerTldBundleDiscoverers;
+    }
+    
+    
+    
     /* ------------------------------------------------------------ */
     public ServerInstanceWrapper(String managedServerName)
     {
@@ -173,9 +191,29 @@
             configure(server, props);
 
             init();
+            
+            //if support for jsp is enabled, we need to convert locations of bundles that contain tlds into urls.
+            //these are tlds that we want jasper to treat as if they are on the container's classpath. Web bundles
+            //can use the Require-TldBundle MANIFEST header to name other tld-containing bundles that should be regarded
+            //as on the webapp classpath.
+            if (!__containerTldBundleDiscoverers.isEmpty())
+            {
+                Set<URL> urls = new HashSet<URL>();
+                //discover bundles with tlds that need to be on the container's classpath as URLs
+                for (TldBundleDiscoverer d:__containerTldBundleDiscoverers)
+                {
+                    URL[] list = d.getUrlsForBundlesWithTlds(_deploymentManager, BundleFileLocatorHelperFactory.getFactory().getHelper());
+                    if (list != null)
+                    {
+                        for (URL u:list)
+                            urls.add(u);
+                    }
+                }
+                _commonParentClassLoaderForWebapps =  new FakeURLClassLoader(libExtClassLoader, urls.toArray(new URL[urls.size()]));
+            }
+            else
+                _commonParentClassLoaderForWebapps = libExtClassLoader;
 
-            URL[] jarsWithTlds = getJarsWithTlds();
-            _commonParentClassLoaderForWebapps = jarsWithTlds == null ? libExtClassLoader : new TldLocatableURLClassloader(libExtClassLoader, jarsWithTlds);
             
             if (LOG.isDebugEnabled()) LOG.debug("common classloader = "+_commonParentClassLoaderForWebapps);
 
@@ -219,54 +257,7 @@
     }
     
     
-    /* ------------------------------------------------------------ */
-    /**
-     * TODO: right now only the jetty-jsp bundle is scanned for common taglibs.
-     * Should support a way to plug more bundles that contain taglibs.
-     * 
-     * The jasper TldScanner expects a URLClassloader to parse a jar for the
-     * /META-INF/*.tld it may contain. We place the bundles that we know contain
-     * such tag-libraries. Please note that it will work if and only if the
-     * bundle is a jar (!) Currently we just hardcode the bundle that contains
-     * the jstl implementation.
-     * 
-     * A workaround when the tld cannot be parsed with this method is to copy
-     * and paste it inside the WEB-INF of the webapplication where it is used.
-     * 
-     * Support only 2 types of packaging for the bundle: - the bundle is a jar
-     * (recommended for runtime.) - the bundle is a folder and contain jars in
-     * the root and/or in the lib folder (nice for PDE development situations)
-     * Unsupported: the bundle is a jar that embeds more jars.
-     * 
-     * @return
-     * @throws Exception
-     */
-    private URL[] getJarsWithTlds() throws Exception
-    {
-        
-        //Jars that are added onto the equivalent of the container classpath are:
-        // jstl jars: identified by the class WhenTag (and the boot-bundle manifest imports the jstl packages
-        // bundles identified by System property org.eclipse.jetty.osgi.tldbundles
-        // bundle symbolic name patterns defined in the DeploymentManager
-        //
-        // Any bundles mentioned in the Require-TldBundle manifest header of the webapp bundle MUST ALSO HAVE Import-Bundle
-        // in order to get them onto the classpath of the webapp.
-        
-        ArrayList<URL> res = new ArrayList<URL>();
-        for (WebappRegistrationCustomizer regCustomizer : WebBundleTrackerCustomizer.JSP_REGISTRATION_HELPERS)
-        {
-            URL[] urls = regCustomizer.getJarsWithTlds(_deploymentManager, BundleFileLocatorHelperFactory.getFactory().getHelper());
-            for (URL url : urls)
-            {
-                if (!res.contains(url)) res.add(url);
-            }
-        }
-        if (!res.isEmpty())
-            return res.toArray(new URL[res.size()]);
-        else
-            return null;
-    }
-    
+   
     
     /* ------------------------------------------------------------ */
     private void configure(Server server, Dictionary props) throws Exception
@@ -340,7 +331,9 @@
         }
 
     }
-
+    
+    
+    /* ------------------------------------------------------------ */
     /**
      * Must be called after the server is configured. 
      * 
@@ -438,7 +431,9 @@
             }
         }
     }
-
+    
+    
+    /* ------------------------------------------------------------ */
     /**
      * @return The default folder in which the context files of the osgi bundles
      *         are located and watched. Or null when the system property
@@ -463,7 +458,7 @@
         return new File(jettyHome, "/contexts");
     }
 
-
+    /* ------------------------------------------------------------ */
     /**
      * @return the urls in this string.
      */
@@ -485,7 +480,9 @@
         }
         return urls;
     }
-
+    
+    
+    /* ------------------------------------------------------------ */
     /**
      * Get the folders that might contain jars for the legacy J2EE shared
      * libraries
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/BundleWatcher.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/BundleWatcher.java
new file mode 100644
index 0000000..74622c3
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/BundleWatcher.java
@@ -0,0 +1,317 @@
+//
+//  ========================================================================
+//  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.osgi.boot.internal.webapp;
+
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.jetty.osgi.boot.BundleProvider;
+import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
+import org.eclipse.jetty.osgi.boot.utils.TldBundleDiscoverer;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * BundleWatcher
+ * 
+ * 
+ * Tracks the installation and removal of Bundles in the OSGi environment. Any bundles
+ * that are added are passed to the set of Jetty DeploymentManager providers to see if
+ * the bundle should be deployed as a webapp or ContextHandler into Jetty.
+ * 
+ * @author hmalphettes
+ */
+public class BundleWatcher implements BundleTrackerCustomizer
+{
+    private static final Logger LOG = Log.getLogger(BundleWatcher.class);
+    
+    public static Collection<TldBundleDiscoverer> JSP_REGISTRATION_HELPERS = new ArrayList<TldBundleDiscoverer>();
+
+
+    public static final String FILTER = "(objectclass=" + BundleProvider.class.getName() + ")";
+    private ServiceTracker _serviceTracker;
+    private BundleTracker _bundleTracker;
+    private boolean _waitForDefaultServer = true;
+    private boolean _defaultServerReady = false;
+    private Bundle _bundle = null;
+    
+ 
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * @throws Exception
+     */
+    public BundleWatcher() throws Exception
+    {
+        _bundle = FrameworkUtil.getBundle(this.getClass());
+        //Track all BundleProviders (Jetty DeploymentManager Providers that can deploy bundles)
+        _serviceTracker = new ServiceTracker(_bundle.getBundleContext(), FrameworkUtil.createFilter(FILTER),null);
+        _serviceTracker.open();
+    }
+    
+    
+    /* ------------------------------------------------------------ */
+    public boolean isWaitForDefaultServer()
+    {
+        return _waitForDefaultServer;
+    }
+
+
+    /* ------------------------------------------------------------ */
+    public void setWaitForDefaultServer(boolean waitForDefaultServer)
+    {
+        _waitForDefaultServer = waitForDefaultServer;
+    }
+
+    
+    /* ------------------------------------------------------------ */
+    public void setBundleTracker (BundleTracker bundleTracker)
+    {
+        _bundleTracker = bundleTracker;
+    }
+
+    
+    /* ------------------------------------------------------------ */
+    public void open () throws Exception
+    {
+        if (_waitForDefaultServer && !_defaultServerReady)
+        {
+            String filter = "(&(objectclass=" + BundleProvider.class.getName() + ")"+
+                    "("+OSGiServerConstants.MANAGED_JETTY_SERVER_NAME+"="+OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME+"))";
+            
+            ServiceTracker defaultServerTracker = new ServiceTracker(_bundle.getBundleContext(), 
+                                                                     FrameworkUtil.createFilter(filter),null)
+            {
+                public Object addingService(ServiceReference reference)
+                {
+                    try
+                    {
+                        Object object = super.addingService(reference);
+                        LOG.debug("Default Jetty Server registered {}", reference);
+                        _defaultServerReady = true;
+                        openBundleTracker();
+                        return object;
+                    }
+                    catch (Exception e)
+                    {
+                        throw new IllegalStateException(e);
+                    }
+                }
+            };
+            defaultServerTracker.open();
+        }
+        else
+            openBundleTracker();
+    }
+
+    /* ------------------------------------------------------------ */
+    /**
+     * @param managedServerName
+     * @return
+     */
+    public Map<ServiceReference, BundleProvider> getDeployers(String managedServerName)
+    {
+        if (managedServerName == null)
+            managedServerName = OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME;
+        
+        Map<ServiceReference, BundleProvider> candidates = new HashMap<ServiceReference, BundleProvider>();
+        
+        ServiceReference[] references = _serviceTracker.getServiceReferences();
+        if (references != null)
+        {
+            for (ServiceReference ref:references)
+            {
+                String name = (String)ref.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);                
+                if (managedServerName.equalsIgnoreCase(name))
+                {
+                    BundleProvider candidate = (BundleProvider)_serviceTracker.getService(ref);
+                    if (candidate != null)
+                        candidates.put(ref, candidate);
+                }
+            }
+        }
+       return candidates;
+    }
+
+    /* ------------------------------------------------------------ */
+    /**
+     * A bundle is being added to the <code>BundleTracker</code>.
+     * 
+     * <p>
+     * This method is called before a bundle which matched the search parameters
+     * of the <code>BundleTracker</code> is added to the
+     * <code>BundleTracker</code>. This method should return the object to be
+     * tracked for the specified <code>Bundle</code>. The returned object is
+     * stored in the <code>BundleTracker</code> and is available from the
+     * {@link BundleTracker#getObject(Bundle) getObject} method.
+     * 
+     * @param bundle The <code>Bundle</code> being added to the
+     *            <code>BundleTracker</code>.
+     * @param event The bundle event which caused this customizer method to be
+     *            called or <code>null</code> if there is no bundle event
+     *            associated with the call to this method.
+     * @return The object to be tracked for the specified <code>Bundle</code>
+     *         object or <code>null</code> if the specified <code>Bundle</code>
+     *         object should not be tracked.
+     */
+    public Object addingBundle(Bundle bundle, BundleEvent event)
+    {
+        if (bundle.getState() == Bundle.ACTIVE)
+        {
+            register(bundle);          
+        }
+        else if (bundle.getState() == Bundle.STOPPING)
+        {
+            unregister(bundle);
+        }
+        else
+        {
+            // we should not be called in that state as
+            // we are registered only for ACTIVE and STOPPING
+        }
+        return null;
+    }
+
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * A bundle tracked by the <code>BundleTracker</code> has been modified.
+     * 
+     * <p>
+     * This method is called when a bundle being tracked by the
+     * <code>BundleTracker</code> has had its state modified.
+     * 
+     * @param bundle The <code>Bundle</code> whose state has been modified.
+     * @param event The bundle event which caused this customizer method to be
+     *            called or <code>null</code> if there is no bundle event
+     *            associated with the call to this method.
+     * @param object The tracked object for the specified bundle.
+     */
+    public void modifiedBundle(Bundle bundle, BundleEvent event, Object object)
+    {
+        if (bundle.getState() == Bundle.STOPPING || bundle.getState() == Bundle.ACTIVE)
+        {
+            unregister(bundle);
+        }
+        if (bundle.getState() == Bundle.ACTIVE)
+        {
+            register(bundle);
+        }
+    }
+
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * A bundle tracked by the <code>BundleTracker</code> has been removed.
+     * 
+     * <p>
+     * This method is called after a bundle is no longer being tracked by the
+     * <code>BundleTracker</code>.
+     * 
+     * @param bundle The <code>Bundle</code> that has been removed.
+     * @param event The bundle event which caused this customizer method to be
+     *            called or <code>null</code> if there is no bundle event
+     *            associated with the call to this method.
+     * @param object The tracked object for the specified bundle.
+     */
+    public void removedBundle(Bundle bundle, BundleEvent event, Object object)
+    {
+        unregister(bundle);
+    }
+
+    
+    protected void openBundleTracker()
+    {
+        _bundleTracker.open();
+    }
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * @param bundle
+     * @return true if this bundle can be deployed into Jetty
+     */
+    private boolean register(Bundle bundle)
+    {
+        if (bundle == null)
+            return false;
+
+        //It might be a bundle that is deployable by Jetty.
+        //Use any named Server instance provided, defaulting to the default Server instance if none supplied
+        boolean deployed = false;
+        String serverName = (String)bundle.getHeaders().get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
+        Map<ServiceReference, BundleProvider> candidates = getDeployers(serverName);
+        if (candidates != null)
+        {
+            Iterator<Entry<ServiceReference, BundleProvider>> itor = candidates.entrySet().iterator();
+            while (!deployed && itor.hasNext())
+            {
+                Entry<ServiceReference, BundleProvider> e = itor.next();
+                try
+                {           
+                    deployed = e.getValue().bundleAdded(bundle);
+                }
+                catch (Exception x)
+                {
+                    LOG.warn("Error deploying bundle for jetty context", x);
+                }
+            }
+        }
+
+        return deployed;
+    }
+
+    /* ------------------------------------------------------------ */
+    /**
+     * @param bundle
+     */
+    private void unregister(Bundle bundle)
+    { 
+        boolean undeployed = false;
+        String serverName = (String)bundle.getHeaders().get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);    
+        Map<ServiceReference, BundleProvider> candidates = getDeployers(serverName);
+        if (candidates != null)
+        {
+            Iterator<Entry<ServiceReference, BundleProvider>> itor = candidates.entrySet().iterator();
+            while (!undeployed && itor.hasNext())
+            {
+                Entry<ServiceReference, BundleProvider> e = itor.next();
+                try
+                {
+                    undeployed = e.getValue().bundleRemoved(bundle);
+                }
+                catch (Exception x)
+                {
+                    LOG.warn("Error undeploying Bundle representing jetty deployable ", x);
+                }
+            }
+        }
+    }
+}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/IWebBundleDeployerHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/IWebBundleDeployerHelper.java
deleted file mode 100644
index 1c5cd3e..0000000
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/IWebBundleDeployerHelper.java
+++ /dev/null
@@ -1,88 +0,0 @@
-//
-//  ========================================================================
-//  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.osgi.boot.internal.webapp;
-
-
-import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.webapp.WebAppContext;
-import org.osgi.framework.Bundle;
-
-/**
- * Internal interface for the class that deploys a webapp on a server. Used as
- * we migrate from the single instance of the jety server to multiple jetty
- * servers.
- */
-public interface IWebBundleDeployerHelper
-{
-
-    /**
-     * when this property is present, the type of context handler registered is
-     * not known in advance.
-     */
-    public static final String INTERNAL_SERVICE_PROP_UNKNOWN_CONTEXT_HANDLER_TYPE = "unknownContextHandlerType";
-
-    /**
-     * Deploy a new web application on the jetty server.
-     * 
-     * @param bundle The bundle
-     * @param webappFolderPath The path to the root of the webapp. Must be a
-     *            path relative to bundle; either an absolute path.
-     * @param contextPath The context path. Must start with "/"
-     * @param extraClasspath
-     * @param overrideBundleInstallLocation
-     * @param requireTldBundle The list of bundles's symbolic names that contain
-     *            tld files that are required by this WAB.
-     * @param webXmlPath
-     * @param defaultWebXmlPath TODO: parameter description
-     * @return The contexthandler created and started
-     * @throws Exception
-     */
-    public abstract WebAppContext registerWebapplication(Bundle bundle, String webappFolderPath, String contextPath, String extraClasspath,
-                                                         String overrideBundleInstallLocation, String requireTldBundle, String webXmlPath,
-                                                         String defaultWebXmlPath, WebAppContext webAppContext) throws Exception;
-
-    /**
-     * Stop a ContextHandler and remove it from the collection.
-     * 
-     * @see ContextDeployer#undeploy
-     * @param contextHandler
-     * @throws Exception
-     */
-    public abstract void unregister(ContextHandler contextHandler) throws Exception;
-
-    /**
-     * This type of registration relies on jetty's complete context xml file.
-     * Context encompasses jndi and all other things. This makes the definition
-     * of the webapp a lot more self-contained.
-     * 
-     * @param contributor
-     * @param contextFileRelativePath
-     * @param extraClasspath
-     * @param overrideBundleInstallLocation
-     * @param requireTldBundle The list of bundles'symbolic name that contain
-     *            tld files for this webapp.
-     * @param handler the context handler passed in the server reference that
-     *            will be configured, deployed and started.
-     * @return The contexthandler created and started
-     * @throws Exception
-     */
-    public abstract ContextHandler registerContext(Bundle contributor, String contextFileRelativePath, String extraClasspath,
-                                                   String overrideBundleInstallLocation, String requireTldBundle, ContextHandler handler) throws Exception;
-
-}
\ No newline at end of file
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/LibExtClassLoaderHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/LibExtClassLoaderHelper.java
index c66fa26..7673834 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/LibExtClassLoaderHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/LibExtClassLoaderHelper.java
@@ -33,6 +33,9 @@
 import org.eclipse.jetty.server.Server;
 
 /**
+ * LibExtClassLoaderHelper
+ * 
+ * 
  * Helper to create a URL class-loader with the jars inside
  * ${jetty.home}/lib/ext and ${jetty.home}/resources. In an ideal world, every
  * library is an OSGi bundle that does loads nicely. To support standard jars or
@@ -40,57 +43,40 @@
  * inserting the jars in the usual jetty/lib/ext folders in the proper classpath
  * for the webapps.
  * <p>
- * Also the folder resources typically contains central configuration files for
- * things like: log config and others. We enable fragments to register classes
- * that are called back and passed those resources to do what they need to do.
+ * The drawback is that those jars will not be available in the OSGi
+ * classloader.
  * </p>
  * <p>
- * For example the test-jndi webapplication depends on derby, derbytools,
- * atomikos none of them are osgi bundles. we can either re-package them or we
- * can place them in the usual lib/ext. <br/>
- * In fact jasper's jsp libraries should maybe place in lib/ext too.
- * </p>
- * <p>
- * The drawback is that those libraries will not be available in the OSGi
- * classloader. Note that we could have setup those jars as embedded jars of the
- * current bundle. However, we would need to know in advance what are those jars
- * which was not acceptable. Also having those jars in a URLClassLoader seem to
- * be required for some cases. For example jaspers' TldLocationsCache (replaced
- * by TldScanner for servlet-3.0). <br/>
- * Also all the dependencies of those libraries must be resolvable directly from
- * the JettyBootstrapActivator bundle as it is set as the parent classloader. For
- * example: if atomikos is placed in lib/ext it will work if and only if
- * JettyBootstrapActivator import the necessary packages from javax.naming*,
- * javax.transaction*, javax.mail* etc Most of the common cases of javax are
- * added as optional import packages into jetty bootstrapper plugin. When there
- * are not covered: please make a request or create a fragment or register a
- * bundle with a buddy-policy onto the jetty bootstrapper..
- * </p>
- * <p>
- * Alternatives to placing jars in lib/ext
+ * Alternatives to placing jars in lib/ext:
  * <ol>
- * <li>Bundle the jars in an osgi bundle. Have the webapp(s) that context
- * depends on them depend on that bundle. Things will go well for jetty.</li>
+ * <li>Bundle the jars in an osgi bundle. Have the webapp(s) that need these jars
+ * depend on that bundle.</li>
  * <li>Bundle those jars in an osgi bundle-fragment that targets the
  * jetty-bootstrap bundle</li>
  * <li>Use equinox Buddy-Policy: register a buddy of the jetty bootstrapper
- * bundle. (least favorite: it will work only on equinox)</li>
+ * bundle. (Note: it will work only on equinox)</li>
  * </ol>
  * </p>
  */
 public class LibExtClassLoaderHelper
 {
-
+    /* ------------------------------------------------------------ */
     /**
-     * Class called back
+     * IFilesInJettyHomeResourcesProcessor
+     * 
+     * Interface for callback impls
      */
     public interface IFilesInJettyHomeResourcesProcessor
     {
         void processFilesInResourcesFolder(File jettyHome, Map<String, File> filesInResourcesFolder);
     }
 
+    
+    
     public static Set<IFilesInJettyHomeResourcesProcessor> registeredFilesInJettyHomeResourcesProcessors = new HashSet<IFilesInJettyHomeResourcesProcessor>();
 
+    
+    /* ------------------------------------------------------------ */
     /**
      * @param server
      * @return a url classloader with the jars of resources, lib/ext and the
@@ -145,6 +131,8 @@
         return new URLClassLoader(urls.toArray(new URL[urls.size()]), parentClassLoader);
     }
 
+    
+    /* ------------------------------------------------------------ */
     /**
      * @param server
      * @return a url classloader with the jars of resources, lib/ext and the
@@ -188,6 +176,7 @@
         return new URLClassLoader(urls.toArray(new URL[urls.size()]), parentClassLoader);
     }
 
+    /* ------------------------------------------------------------ */
     /**
      * When we find files typically used for central logging configuration we do
      * what it takes in this method to do what the user expects. Without
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java
index 5f7e644..e963b91 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/OSGiWebappClassLoader.java
@@ -33,7 +33,6 @@
 
 import javax.servlet.http.HttpServlet;
 
-import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelper;
 import org.eclipse.jetty.osgi.boot.utils.BundleClassLoaderHelperFactory;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.Logger;
@@ -44,8 +43,10 @@
 import org.osgi.framework.BundleReference;
 
 /**
- * Extends the webappclassloader to insert the classloader provided by the osgi
- * bundle at the same level than any other jars palced in the webappclassloader.
+ * OSGiWebappClassLoader
+ * 
+ * 
+ * Extends the webapp classloader to also use the classloader of the Bundle defining the webapp.
  */
 public class OSGiWebappClassLoader extends WebAppClassLoader implements BundleReference
 {
@@ -79,10 +80,9 @@
 
     private boolean _lookInOsgiFirst = true;
 
-    private Set<String> _libsAlreadyInManifest = new HashSet<String>();
-
+    /* ------------------------------------------------------------ */
     /**
-     * @param parent The parent classloader. In this case
+     * @param parent The parent classloader.
      * @param context The WebAppContext
      * @param contributor The bundle that defines this web-application.
      * @throws IOException
@@ -94,7 +94,10 @@
         _contributor = contributor;
         _osgiBundleClassLoader = BundleClassLoaderHelperFactory.getFactory().getHelper().getBundleClassLoader(contributor);
     }
-
+    
+    
+    
+    /* ------------------------------------------------------------ */
     /**
      * Returns the <code>Bundle</code> that defined this web-application.
      * 
@@ -106,17 +109,7 @@
         return _contributor;
     }
 
-    /**
-     * Reads the manifest. If the manifest is already configured to loads a few
-     * libs we should not add them to the classpath of the webapp. Not really
-     * important as we resolve classes through the osgi classloader first and
-     * then default on the libs of the webapp.
-     */
-    private void computeLibsAlreadyInOSGiClassLoader()
-    {
-        // TODO
-    }
-
+    /* ------------------------------------------------------------ */
     @Override
     public Enumeration<URL> getResources(String name) throws IOException
     {
@@ -131,7 +124,10 @@
             return Collections.enumeration(toList(urls, osgiUrls));
         }
     }
-
+    
+    
+    
+    /* ------------------------------------------------------------ */
     @Override
     public URL getResource(String name)
     {
@@ -146,7 +142,10 @@
             return url != null ? url : _osgiBundleClassLoader.getResource(name);
         }
     }
-
+    
+    
+    
+    /* ------------------------------------------------------------ */
     private List<URL> toList(Enumeration<URL> e, Enumeration<URL> e2)
     {
         List<URL> list = new ArrayList<URL>();
@@ -157,9 +156,8 @@
         return list;
     }
 
-    /**
-     * 
-     */
+    
+    /* ------------------------------------------------------------ */
     protected Class<?> findClass(String name) throws ClassNotFoundException
     {
         try
@@ -178,7 +176,10 @@
             }
         }
     }
-
+    
+    
+    
+    /* ------------------------------------------------------------ */
     /**
      * Parse the classpath ourselves to be able to filter things. This is a
      * derivative work of the super class
@@ -207,6 +208,8 @@
 
     }
 
+    
+    /* ------------------------------------------------------------ */
     /**
      * @param lib
      * @return true if the lib should be included in the webapp classloader.
@@ -255,6 +258,8 @@
 
     private static Field _contextField;
 
+    
+    /* ------------------------------------------------------------ */
     /**
      * In the case of the generation of a webapp via a jetty context file we
      * need a proper classloader to setup the app before we have the
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/ServiceWatcher.java
similarity index 91%
rename from jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java
rename to jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/ServiceWatcher.java
index 6bd352d..08dbd4a 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/JettyContextHandlerServiceTracker.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/ServiceWatcher.java
@@ -18,28 +18,18 @@
 
 package org.eclipse.jetty.osgi.boot.internal.webapp;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 
-import org.eclipse.jetty.osgi.boot.BundleWebAppProvider;
 import org.eclipse.jetty.osgi.boot.JettyBootstrapActivator;
 import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
 import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
 import org.eclipse.jetty.osgi.boot.ServiceProvider;
-import org.eclipse.jetty.osgi.boot.internal.serverfactory.DefaultJettyAtJettyHomeHelper;
-import org.eclipse.jetty.osgi.boot.internal.serverfactory.IManagedJettyServerRegistry;
-import org.eclipse.jetty.osgi.boot.internal.serverfactory.ServerInstanceWrapper;
 import org.eclipse.jetty.server.handler.ContextHandler;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.Logger;
-import org.eclipse.jetty.util.Scanner;
-import org.eclipse.jetty.webapp.WebAppContext;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
@@ -49,7 +39,7 @@
 import org.osgi.util.tracker.ServiceTracker;
 
 /**
- * JettyContextHandlerServiceTracker
+ * ServiceWatcher
  * 
  * When a {@link ContextHandler} is activated as an osgi service we find a jetty deployer
  * for it. The ContextHandler could be either a WebAppContext or any other derivative of 
@@ -59,9 +49,9 @@
  * osgi services. Instead, they can be deployed via manifest headers inside bundles. See
  * {@link WebBundleTrackerCustomizer}.
  */
-public class JettyContextHandlerServiceTracker implements ServiceListener
+public class ServiceWatcher implements ServiceListener
 {
-    private static Logger LOG = Log.getLogger(JettyContextHandlerServiceTracker.class);
+    private static Logger LOG = Log.getLogger(ServiceWatcher.class);
     
     public static final String FILTER = "(objectclass=" + ServiceProvider.class.getName() + ")";
 
@@ -75,7 +65,7 @@
     /**
      * @param registry
      */
-    public JettyContextHandlerServiceTracker() throws Exception
+    public ServiceWatcher() throws Exception
     {
         //track all instances of deployers of webapps
         Bundle myBundle = FrameworkUtil.getBundle(this.getClass());
@@ -195,6 +185,7 @@
                         try
                         {
                             added = e.getValue().serviceAdded(sr, contextHandler);
+                            System.err.println(serverName+" deployed "+contextHandler+": "+added);
                             if (added && LOG.isDebugEnabled())
                                 LOG.debug("Provider "+e.getValue()+" deployed "+contextHandler);
                         }
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java
deleted file mode 100644
index b8adc65..0000000
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/internal/webapp/WebBundleTrackerCustomizer.java
+++ /dev/null
@@ -1,250 +0,0 @@
-//
-//  ========================================================================
-//  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.osgi.boot.internal.webapp;
-
-
-import java.util.ArrayList;
-import java.util.Collection;
-
-import org.eclipse.jetty.osgi.boot.BundleProvider;
-import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
-import org.eclipse.jetty.osgi.boot.utils.WebappRegistrationCustomizer;
-import org.eclipse.jetty.util.log.Log;
-import org.eclipse.jetty.util.log.Logger;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceReference;
-import org.osgi.util.tracker.BundleTracker;
-import org.osgi.util.tracker.BundleTrackerCustomizer;
-import org.osgi.util.tracker.ServiceTracker;
-
-/**
- * WebBundleTrackerCustomizer
- * 
- * 
- * Support bundles that declare a webpp or context directly through headers in their
- * manifest. They will be deployed to the default jetty Server instance.
- * 
- * If you wish to deploy a context or webapp to a different jetty Server instance,
- * register your context/webapp as an osgi service, and set the property OSGiServerConstants.MANAGED_JETTY_SERVER_NAME
- * with the name of the Server instance you wish to depoy to.
- * 
- * @author hmalphettes
- */
-public class WebBundleTrackerCustomizer implements BundleTrackerCustomizer
-{
-    private static final Logger LOG = Log.getLogger(WebBundleTrackerCustomizer.class);
-    
-    public static Collection<WebappRegistrationCustomizer> JSP_REGISTRATION_HELPERS = new ArrayList<WebappRegistrationCustomizer>();
-    public static final String FILTER = "(&(objectclass=" + BundleProvider.class.getName() + ")"+
-                                          "("+OSGiServerConstants.MANAGED_JETTY_SERVER_NAME+"="+OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME+"))";
-
-    private ServiceTracker _serviceTracker;
-    private BundleTracker _bundleTracker;
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * @throws Exception
-     */
-    public WebBundleTrackerCustomizer ()
-    throws Exception
-    {
-        Bundle myBundle = FrameworkUtil.getBundle(this.getClass());
-        
-        //track all instances of deployers of webapps/contexts as bundles       
-        _serviceTracker = new ServiceTracker(myBundle.getBundleContext(), FrameworkUtil.createFilter(FILTER),null) {
-            public Object addingService(ServiceReference reference) {
-                Object object = super.addingService(reference);
-                LOG.debug("Deployer registered {}", reference);
-                openBundleTracker();
-                return object;
-            }
-        };
-        _serviceTracker.open();
-
-    }
-    
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * A bundle is being added to the <code>BundleTracker</code>.
-     * 
-     * <p>
-     * This method is called before a bundle which matched the search parameters
-     * of the <code>BundleTracker</code> is added to the
-     * <code>BundleTracker</code>. This method should return the object to be
-     * tracked for the specified <code>Bundle</code>. The returned object is
-     * stored in the <code>BundleTracker</code> and is available from the
-     * {@link BundleTracker#getObject(Bundle) getObject} method.
-     * 
-     * @param bundle The <code>Bundle</code> being added to the
-     *            <code>BundleTracker</code>.
-     * @param event The bundle event which caused this customizer method to be
-     *            called or <code>null</code> if there is no bundle event
-     *            associated with the call to this method.
-     * @return The object to be tracked for the specified <code>Bundle</code>
-     *         object or <code>null</code> if the specified <code>Bundle</code>
-     *         object should not be tracked.
-     */
-    public Object addingBundle(Bundle bundle, BundleEvent event)
-    {
-        if (bundle.getState() == Bundle.ACTIVE)
-        {
-            register(bundle);          
-        }
-        else if (bundle.getState() == Bundle.STOPPING)
-        {
-            unregister(bundle);
-        }
-        else
-        {
-            // we should not be called in that state as
-            // we are registered only for ACTIVE and STOPPING
-        }
-        return null;
-    }
-
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * A bundle tracked by the <code>BundleTracker</code> has been modified.
-     * 
-     * <p>
-     * This method is called when a bundle being tracked by the
-     * <code>BundleTracker</code> has had its state modified.
-     * 
-     * @param bundle The <code>Bundle</code> whose state has been modified.
-     * @param event The bundle event which caused this customizer method to be
-     *            called or <code>null</code> if there is no bundle event
-     *            associated with the call to this method.
-     * @param object The tracked object for the specified bundle.
-     */
-    public void modifiedBundle(Bundle bundle, BundleEvent event, Object object)
-    {
-        // nothing the web-bundle was already track. something changed.
-        // we only reload the webapps if the bundle is stopped and restarted.
-        if (bundle.getState() == Bundle.STOPPING || bundle.getState() == Bundle.ACTIVE)
-        {
-            unregister(bundle);
-        }
-        if (bundle.getState() == Bundle.ACTIVE)
-        {
-            register(bundle);
-        }
-    }
-
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * A bundle tracked by the <code>BundleTracker</code> has been removed.
-     * 
-     * <p>
-     * This method is called after a bundle is no longer being tracked by the
-     * <code>BundleTracker</code>.
-     * 
-     * @param bundle The <code>Bundle</code> that has been removed.
-     * @param event The bundle event which caused this customizer method to be
-     *            called or <code>null</code> if there is no bundle event
-     *            associated with the call to this method.
-     * @param object The tracked object for the specified bundle.
-     */
-    public void removedBundle(Bundle bundle, BundleEvent event, Object object)
-    {
-        unregister(bundle);
-    }
-
-    
-    /* ------------------------------------------------------------ */
-    /**
-     * @param bundle
-     * @return true if this bundle in indeed a web-bundle.
-     */
-    private boolean register(Bundle bundle)
-    {
-        if (bundle == null)
-            return false;
-
-        //It might be a bundle that we can deploy to our default jetty server instance
-        boolean deployed = false;
-        Object[] deployers = _serviceTracker.getServices();
-        if (deployers != null)
-        {
-            int i=0;
-            while (!deployed && i<deployers.length)
-            {
-
-                BundleProvider p = (BundleProvider)deployers[i];
-                try
-                {
-                    deployed = p.bundleAdded(bundle);
-                }
-                catch (Exception x)
-                {
-                    LOG.warn("Error deploying bundle for jetty context", x);
-                }
-                i++;
-            }
-        }
-
-        return deployed;
-    }
-
-    /* ------------------------------------------------------------ */
-    /**
-     * @param bundle
-     */
-    private void unregister(Bundle bundle)
-    { 
-        Object[] deployers = _serviceTracker.getServices();
-        boolean undeployed = false;
-        if (deployers != null)
-        {
-            int i=0;
-            while (!undeployed && i<deployers.length)
-            {
-                try
-                {
-                    undeployed = ((BundleProvider)deployers[i++]).bundleRemoved(bundle);
-                }
-                catch (Exception x)
-                {
-                    LOG.warn("Error undeploying bundle for jetty context", x);
-                }
-            }
-        }
-    }
-
-    public void setAndOpenWebBundleTracker(BundleTracker bundleTracker) {
-        if(_bundleTracker == null) {
-            _bundleTracker = bundleTracker;
-            LOG.debug("Bundle tracker is set");
-            openBundleTracker();
-        }
-    }
-
-    private void openBundleTracker() {
-        if(_bundleTracker != null && _serviceTracker.getServices() != null &&
-                _serviceTracker.getServices().length > 0) {
-            _bundleTracker.open();
-            LOG.debug("Bundle tracker has been opened");
-        }
-    }
-
-}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelper.java
index 4c4382f..ba99ac2 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelper.java
@@ -22,6 +22,10 @@
 import org.osgi.framework.Bundle;
 
 /**
+ * 
+ * BundleClassLoaderHelper
+ * 
+ * 
  * Is there a clean OSGi way to go from the Bundle object to the classloader of
  * the Bundle ? You can certainly take a class inside the bundle and get the
  * bundle's classloader that way. Getting the classloader directly from the
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelperFactory.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelperFactory.java
index edcfde0..297f0f3 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelperFactory.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleClassLoaderHelperFactory.java
@@ -32,15 +32,19 @@
     
     private static BundleClassLoaderHelperFactory _instance = new BundleClassLoaderHelperFactory();
     
+    
+    /* ------------------------------------------------------------ */
     public static BundleClassLoaderHelperFactory getFactory()
     {
         return _instance;
     }
     
+    /* ------------------------------------------------------------ */
     private BundleClassLoaderHelperFactory()
     {
     }
     
+    /* ------------------------------------------------------------ */
     public BundleClassLoaderHelper getHelper()
     {
         //use the default
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleFileLocatorHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleFileLocatorHelper.java
index 0809b72..2abd7a0 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleFileLocatorHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/BundleFileLocatorHelper.java
@@ -26,6 +26,9 @@
 import org.osgi.framework.Bundle;
 
 /**
+ * BundleFileLocatorHelper
+ * 
+ * 
  * From a bundle to its location on the filesystem. Assumes the bundle is not a
  * jar.
  * 
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/EventSender.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/EventSender.java
index 13703fa..c4e06a2 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/EventSender.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/EventSender.java
@@ -21,14 +21,18 @@
 import java.util.Dictionary;
 import java.util.Hashtable;
 
-import javax.security.auth.login.FailedLoginException;
-
 import org.osgi.framework.Bundle;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.ServiceReference;
 import org.osgi.service.event.Event;
 import org.osgi.service.event.EventAdmin;
 
+/**
+ * EventSender
+ *
+ * Utility class for emiting OSGi EventAdmin events
+ * 
+ */
 public class EventSender
 {    
     //OSGi Event Admin events for webapps
@@ -43,6 +47,13 @@
     private Bundle _myBundle;
     private EventAdmin _eventAdmin;
     
+    
+    
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * 
+     */
     private EventSender ()
     {
         _myBundle = FrameworkUtil.getBundle(EventSender.class);
@@ -50,13 +61,27 @@
         if (ref != null)
             _eventAdmin = (EventAdmin)_myBundle.getBundleContext().getService(ref);
     }
-
     
+    
+    
+
+    /* ------------------------------------------------------------ */
+    /**
+     * @return
+     */
     public static EventSender getInstance()
     {
         return __instance;
     }
 
+    
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * @param topic
+     * @param wab
+     * @param contextPath
+     */
     public  void send (String topic, Bundle wab, String contextPath)
     {
         if (topic==null || wab==null || contextPath==null)
@@ -66,6 +91,14 @@
     }
     
     
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * @param topic
+     * @param wab
+     * @param contextPath
+     * @param ex
+     */
     public  void send (String topic, Bundle wab, String contextPath, Exception ex)
     {        
         if (_eventAdmin == null)
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/FakeURLClassLoader.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/FakeURLClassLoader.java
new file mode 100644
index 0000000..77f8510
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/FakeURLClassLoader.java
@@ -0,0 +1,83 @@
+//
+//  ========================================================================
+//  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.osgi.boot.utils;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+
+/**
+ * 
+ * FakeURLClassLoader
+ * 
+ * A URLClassloader that overrides the getURLs() method to return the list
+ * of urls passed in to the constructor, but otherwise acts as if it has no
+ * urls, which would cause it to delegate to the parent classloader (in this
+ * case an OSGi classloader).
+ * 
+ * The main use of this class is with jars containing tlds. Jasper expects a
+ * URL classloader to inspect for jars with tlds.
+ * 
+ */
+public class FakeURLClassLoader extends URLClassLoader
+{
+
+    private URL[] _jars;
+    
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * @param osgiClassLoader
+     * @param jars
+     */
+    public FakeURLClassLoader(ClassLoader osgiClassLoader, URL[] jars)
+    {
+        super(new URL[] {},osgiClassLoader);
+        _jars = jars;
+    }
+
+    /* ------------------------------------------------------------ */
+    /**
+     * @return the jars that contains tlds so that TldLocationsCache or
+     *         TldScanner can find them.
+     */
+    @Override
+    public URL[] getURLs()
+    {
+        return _jars;
+    }
+
+    
+    /* ------------------------------------------------------------ */
+    /** 
+     * @see java.lang.Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder builder = new StringBuilder();
+
+        if (_jars != null)
+        {
+            for (URL u:_jars)
+                builder.append(" "+u.toString());
+            return builder.toString();
+        }
+        else
+            return super.toString();
+    }
+}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/OSGiClassLoader.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/OSGiClassLoader.java
index 8850f5e..91f42af 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/OSGiClassLoader.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/OSGiClassLoader.java
@@ -78,8 +78,7 @@
         }
 
         if (url == null)
-        {
-            
+        {           
             url = _osgiBundleClassLoader.getResource(name);
 
             if (url == null && name.startsWith("/"))
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/TldBundleDiscoverer.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/TldBundleDiscoverer.java
new file mode 100644
index 0000000..bdd6168
--- /dev/null
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/TldBundleDiscoverer.java
@@ -0,0 +1,43 @@
+//
+//  ========================================================================
+//  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.osgi.boot.utils;
+
+import java.net.URL;
+
+import org.eclipse.jetty.deploy.DeploymentManager;
+
+
+/**
+ * TldBundleDiscoverer
+ * 
+ * Convert bundles that contain tlds into URL locations for consumption by jasper.
+ */
+public interface TldBundleDiscoverer
+{
+    /**
+     * Find bundles that contain tlds and convert into URL references to their location.
+     * 
+     * @param manager
+     * @param fileLocator
+     * @return array of URLs representing locations of tld containing bundles
+     * @throws Exception
+     */
+    URL[] getUrlsForBundlesWithTlds(DeploymentManager manager, BundleFileLocatorHelper fileLocator) throws Exception;
+
+}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/WebappRegistrationCustomizer.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/WebappRegistrationCustomizer.java
deleted file mode 100644
index 813bff4..0000000
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/WebappRegistrationCustomizer.java
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-//  ========================================================================
-//  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.osgi.boot.utils;
-
-import java.net.URL;
-
-import org.eclipse.jetty.deploy.DeploymentManager;
-
-
-/**
- * Fix various shortcomings with the way jasper parses the tld files.
- */
-public interface WebappRegistrationCustomizer
-{
-    /**
-     * we could do something a lot more pluggable with a custom header in the
-     * manifest or some customer declarative services let's keep it simple for
-     * now. hopefully the rest of the world won't need to customize this.
-     */
-    public static final String CLASS_NAME = "org.eclipse.jetty.osgi.boot.jasper.WebappRegistrationCustomizerImpl";
-
-    /**
-     * TODO: right now only the jetty-jsp bundle is scanned for common taglibs.
-     * Should support a way to plug more bundles that contain taglibs.
-     * 
-     * The jasper TldScanner expects a URLClassloader to parse a jar for the
-     * /META-INF/*.tld it may contain. We place the bundles that we know contain
-     * such tag-libraries. Please note that it will work if and only if the
-     * bundle is a jar (!) Currently we just hardcode the bundle that contains
-     * the jstl implemenation.
-     * 
-     * A workaround when the tld cannot be parsed with this method is to copy
-     * and paste it inside the WEB-INF of the webapplication where it is used.
-     * 
-     * Support only 2 types of packaging for the bundle: - the bundle is a jar
-     * (recommended for runtime.) - the bundle is a folder and contain jars in
-     * the root and/or in the lib folder (nice for PDE developement situations)
-     * Unsupported: the bundle is a jar that embeds more jars.
-     * 
-     * @return array of URLs
-     * @throws Exception
-     */
-    URL[] getJarsWithTlds(DeploymentManager manager, BundleFileLocatorHelper fileLocator) throws Exception;
-
-}
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultBundleClassLoaderHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultBundleClassLoaderHelper.java
index 9bb074a..ee0d7c2 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultBundleClassLoaderHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultBundleClassLoaderHelper.java
@@ -28,6 +28,9 @@
 import org.osgi.framework.Bundle;
 
 /**
+ * DefaultBundleClassLoaderHelper
+ * 
+ * 
  * Default implementation of the BundleClassLoaderHelper. Uses introspection to
  * support equinox-3.5 and felix-2.0.0
  */
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java
index 2d31459..7349cd0 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/DefaultFileLocatorHelper.java
@@ -31,11 +31,14 @@
 
 import org.eclipse.jetty.osgi.boot.utils.BundleFileLocatorHelper;
 import org.eclipse.jetty.util.URIUtil;
-import org.eclipse.jetty.util.resource.Resource;
 import org.eclipse.jetty.util.resource.FileResource;
+import org.eclipse.jetty.util.resource.Resource;
 import org.osgi.framework.Bundle;
 
 /**
+ * DefaultFileLocatorHelper
+ * 
+ * 
  * From a bundle to its location on the filesystem. Assumes the bundle is not a
  * jar.
  * 
diff --git a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/PackageAdminServiceTracker.java b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/PackageAdminServiceTracker.java
index 384b392..7ce7551 100644
--- a/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/PackageAdminServiceTracker.java
+++ b/jetty-osgi/jetty-osgi-boot/src/main/java/org/eclipse/jetty/osgi/boot/utils/internal/PackageAdminServiceTracker.java
@@ -35,8 +35,14 @@
 import org.osgi.service.startlevel.StartLevel;
 
 /**
+ * PackageAdminServiceTracker
+ * 
+ * 
  * When the PackageAdmin service is activated we can look for the fragments
- * attached to this bundle and "activate" them.
+ * attached to this bundle and do a fake "activate" on them.
+ * 
+ * See particularly the jetty-osgi-boot-jsp fragment bundle that uses this
+ * facility.
  */
 public class PackageAdminServiceTracker implements ServiceListener
 {
diff --git a/jetty-osgi/jetty-osgi-httpservice/pom.xml b/jetty-osgi/jetty-osgi-httpservice/pom.xml
index 2f17b54..db9872a 100644
--- a/jetty-osgi/jetty-osgi-httpservice/pom.xml
+++ b/jetty-osgi/jetty-osgi-httpservice/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty.osgi</groupId>
     <artifactId>jetty-osgi-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-httpservice</artifactId>
diff --git a/jetty-osgi/jetty-osgi-npn/pom.xml b/jetty-osgi/jetty-osgi-npn/pom.xml
index 1d71cbb..0515eaa 100644
--- a/jetty-osgi/jetty-osgi-npn/pom.xml
+++ b/jetty-osgi/jetty-osgi-npn/pom.xml
@@ -1,9 +1,8 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
   <parent>
     <groupId>org.eclipse.jetty.osgi</groupId>
     <artifactId>jetty-osgi-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-osgi-npn</artifactId>
diff --git a/jetty-osgi/pom.xml b/jetty-osgi/pom.xml
index 0e98d1d..bcf9990 100644
--- a/jetty-osgi/pom.xml
+++ b/jetty-osgi/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <groupId>org.eclipse.jetty.osgi</groupId>
   <artifactId>jetty-osgi-project</artifactId>
diff --git a/jetty-osgi/test-jetty-osgi-context/pom.xml b/jetty-osgi/test-jetty-osgi-context/pom.xml
index 8b4eecc..03634fd 100644
--- a/jetty-osgi/test-jetty-osgi-context/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-context/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty.osgi</groupId>
     <artifactId>jetty-osgi-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>test-jetty-osgi-context</artifactId>
diff --git a/jetty-osgi/test-jetty-osgi-webapp/pom.xml b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
index b3ea3e6..444840f 100644
--- a/jetty-osgi/test-jetty-osgi-webapp/pom.xml
+++ b/jetty-osgi/test-jetty-osgi-webapp/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty.osgi</groupId>
     <artifactId>jetty-osgi-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-osgi/test-jetty-osgi/pom.xml b/jetty-osgi/test-jetty-osgi/pom.xml
index e673df1..85d0989 100644
--- a/jetty-osgi/test-jetty-osgi/pom.xml
+++ b/jetty-osgi/test-jetty-osgi/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty.osgi</groupId>
     <artifactId>jetty-osgi-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-plus/pom.xml b/jetty-plus/pom.xml
index 4aeff75..d1bacea 100644
--- a/jetty-plus/pom.xml
+++ b/jetty-plus/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-plus</artifactId>
diff --git a/jetty-proxy/pom.xml b/jetty-proxy/pom.xml
index ce2e37e..27353e1 100644
--- a/jetty-proxy/pom.xml
+++ b/jetty-proxy/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-proxy</artifactId>
diff --git a/jetty-rewrite/pom.xml b/jetty-rewrite/pom.xml
index a54c6cb..cdbf469 100644
--- a/jetty-rewrite/pom.xml
+++ b/jetty-rewrite/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-rewrite</artifactId>
diff --git a/jetty-runner/pom.xml b/jetty-runner/pom.xml
index c1b42e9..ec57a92 100644
--- a/jetty-runner/pom.xml
+++ b/jetty-runner/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>org.eclipse.jetty</groupId>
diff --git a/jetty-security/pom.xml b/jetty-security/pom.xml
index a13eef1..9aa83c7 100644
--- a/jetty-security/pom.xml
+++ b/jetty-security/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-security</artifactId>
diff --git a/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java b/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java
index a606a0c..7878479 100644
--- a/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java
+++ b/jetty-security/src/main/java/org/eclipse/jetty/security/ConstraintSecurityHandler.java
@@ -696,6 +696,7 @@
 
         HttpConfiguration httpConfig = HttpChannel.getCurrentHttpChannel().getHttpConfiguration();
 
+
         if (dataConstraint == UserDataConstraint.Confidential || dataConstraint == UserDataConstraint.Integral)
         {
             if (request.isSecure())
@@ -703,11 +704,13 @@
 
             if (httpConfig.getSecurePort() > 0)
             {
-                String url = httpConfig.getSecureScheme() + "://" + request.getServerName() + ":" + httpConfig.getSecurePort()
-                        + request.getRequestURI();
+                String scheme = httpConfig.getSecureScheme();
+                int port = httpConfig.getSecurePort();
+                String url = ("https".equalsIgnoreCase(scheme) && port==443)
+                    ? "https://"+request.getServerName()+request.getRequestURI()
+                    : scheme + "://" + request.getServerName() + ":" + port + request.getRequestURI();                    
                 if (request.getQueryString() != null)
                     url += "?" + request.getQueryString();
-
                 response.setContentLength(0);
                 response.sendRedirect(url);
             }
diff --git a/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java b/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java
index dc4b13b..abbfe73 100644
--- a/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java
+++ b/jetty-security/src/test/java/org/eclipse/jetty/security/ConstraintTest.java
@@ -41,6 +41,8 @@
 import org.eclipse.jetty.security.authentication.BasicAuthenticator;
 import org.eclipse.jetty.security.authentication.FormAuthenticator;
 import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
 import org.eclipse.jetty.server.LocalConnector;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.Server;
@@ -65,12 +67,14 @@
     private Server _server;
     private LocalConnector _connector;
     private ConstraintSecurityHandler _security;
+    private HttpConfiguration _config;
 
     @Before
     public void startServer()
     {
         _server = new Server();
         _connector = new LocalConnector(_server);
+        _config=_connector.getConnectionFactory(HttpConnectionFactory.class).getHttpConfiguration();
         _server.setConnectors(new Connector[]{_connector});
 
         ContextHandler _context = new ContextHandler();
@@ -161,7 +165,15 @@
         mapping5.setConstraint(constraint5);
         mapping5.setMethod("POST");
 
-        return Arrays.asList(mapping0, mapping1, mapping2, mapping3, mapping4, mapping5);
+        Constraint constraint6 = new Constraint();
+        constraint6.setAuthenticate(false);
+        constraint6.setName("data constraint");
+        constraint6.setDataConstraint(2);
+        ConstraintMapping mapping6 = new ConstraintMapping();
+        mapping6.setPathSpec("/data/*");
+        mapping6.setConstraint(constraint6);
+        
+        return Arrays.asList(mapping0, mapping1, mapping2, mapping3, mapping4, mapping5, mapping6);
     }
 
     @Test
@@ -742,9 +754,9 @@
         response = _connector.getResponses("GET /ctx/forbid/info HTTP/1.0\r\n\r\n");
         assertThat(response,startsWith("HTTP/1.1 403 Forbidden"));
 
-        response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\n\r\n");
+        response = _connector.getResponses("GET /ctx/auth/info HTTP/1.0\r\nHost:wibble.com:8888\r\n\r\n");
         assertThat(response,containsString(" 302 Found"));
-        assertThat(response,containsString("/ctx/testLoginPage"));
+        assertThat(response,containsString("http://wibble.com:8888/ctx/testLoginPage"));
 
         String session = response.substring(response.indexOf("JSESSIONID=") + 11, response.indexOf(";Path=/ctx"));
 
@@ -840,6 +852,48 @@
         assertThat(response,startsWith("HTTP/1.1 200 OK"));
     }
 
+
+
+    @Test
+    public void testDataRedirection() throws Exception
+    {
+        _security.setAuthenticator(new BasicAuthenticator());
+        _server.start();
+
+        String response;
+
+        response = _connector.getResponses("GET /ctx/data/info HTTP/1.0\r\n\r\n");
+        assertTrue(response.startsWith("HTTP/1.1 403"));
+        
+        _config.setSecurePort(8443);
+        _config.setSecureScheme("https");
+
+        response = _connector.getResponses("GET /ctx/data/info HTTP/1.0\r\n\r\n");
+        assertTrue(response.startsWith("HTTP/1.1 302 Found"));
+        assertTrue(response.indexOf("Location") > 0);
+        assertTrue(response.indexOf(":8443/ctx/data/info") > 0);
+
+        _config.setSecurePort(443);
+        response = _connector.getResponses("GET /ctx/data/info HTTP/1.0\r\n\r\n");
+        assertTrue(response.startsWith("HTTP/1.1 302 Found"));
+        assertTrue(response.indexOf("Location") > 0);
+        assertTrue(response.indexOf(":443/ctx/data/info") < 0);
+
+        _config.setSecurePort(8443);
+        response = _connector.getResponses("GET /ctx/data/info HTTP/1.0\r\nHost: wobble.com\r\n\r\n");
+        assertTrue(response.startsWith("HTTP/1.1 302 Found"));
+        assertTrue(response.indexOf("Location") > 0);
+        assertTrue(response.indexOf("https://wobble.com:8443/ctx/data/info") > 0);
+
+        _config.setSecurePort(443);
+        response = _connector.getResponses("GET /ctx/data/info HTTP/1.0\r\nHost: wobble.com\r\n\r\n");
+        System.err.println(response);
+        assertTrue(response.startsWith("HTTP/1.1 302 Found"));
+        assertTrue(response.indexOf("Location") > 0);
+        assertTrue(response.indexOf(":443") < 0);
+        assertTrue(response.indexOf("https://wobble.com/ctx/data/info") > 0);
+    }
+    
     @Test
     public void testRoleRef() throws Exception
     {
diff --git a/jetty-server/pom.xml b/jetty-server/pom.xml
index 577d57e..04c86c6 100644
--- a/jetty-server/pom.xml
+++ b/jetty-server/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-server</artifactId>
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
index bcc13aa..28fea90 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AbstractConnector.java
@@ -151,6 +151,7 @@
     private long _idleTimeout = 30000;
     private String _defaultProtocol;
     private ConnectionFactory _defaultConnectionFactory;
+    private String _name;
 
 
     /**
@@ -288,8 +289,9 @@
 
         // If we have a stop timeout
         long stopTimeout = getStopTimeout();
-        if (stopTimeout > 0 && _stopping!=null)
-            _stopping.await(stopTimeout,TimeUnit.MILLISECONDS);
+        CountDownLatch stopping=_stopping;
+        if (stopTimeout > 0 && stopping!=null)
+            stopping.await(stopTimeout,TimeUnit.MILLISECONDS);
         _stopping=null;
 
         super.doStop();
@@ -474,7 +476,9 @@
                 {
                     _acceptors[_acceptor] = null;
                 }
-                _stopping.countDown();
+                CountDownLatch stopping=_stopping;
+                if (stopping!=null)
+                    stopping.countDown();
             }
         }
     }
@@ -525,10 +529,28 @@
     }
 
     @Override
+    public String getName()
+    {
+        return _name;
+    }
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * Set a connector name.   A context may be configured with
+     * virtual hosts in the form "@contextname" and will only serve
+     * requests from the named connector,
+     * @param name A connector name.
+     */
+    public void setName(String name)
+    {
+        _name=name;
+    }
+    
+    @Override
     public String toString()
     {
         return String.format("%s@%x{%s}",
-                getClass().getSimpleName(),
+                _name==null?getClass().getSimpleName():_name,
                 hashCode(),
                 getDefaultProtocol());
     }
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncNCSARequestLog.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncNCSARequestLog.java
index 047e3b6..300d23c 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncNCSARequestLog.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncNCSARequestLog.java
@@ -57,7 +57,7 @@
     {
         super(filename);
         if (queue==null)
-            queue=new ConcurrentArrayBlockingQueue.Bounded<String>(1024);
+            queue=new ConcurrentArrayBlockingQueue.Unbounded<String>();
         _queue=queue;
     }
 
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java b/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java
index 3454c78..6866e5e 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/Connector.java
@@ -24,6 +24,7 @@
 
 import org.eclipse.jetty.io.ByteBufferPool;
 import org.eclipse.jetty.io.EndPoint;
+import org.eclipse.jetty.server.handler.ContextHandler;
 import org.eclipse.jetty.util.annotation.ManagedAttribute;
 import org.eclipse.jetty.util.annotation.ManagedObject;
 import org.eclipse.jetty.util.component.Graceful;
@@ -90,4 +91,15 @@
      * @return immutable collection of connected endpoints
      */
     public Collection<EndPoint> getConnectedEndPoints();
+
+    
+    /* ------------------------------------------------------------ */
+    /**
+     * Get the connector name if set.
+     * <p>A {@link ContextHandler} may be configured with
+     * virtual hosts in the form "@connectorName" and will only serve
+     * requests from the named connector.
+     * @return The connector name or null.
+     */
+    public String getName();
 }
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java b/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java
index aba2995..e789d38 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/ShutdownMonitor.java
@@ -146,6 +146,7 @@
         {
             if (isAlive())
             {
+                // TODO why are we reentrant here?
                 if (DEBUG)
                     System.err.printf("ShutdownMonitorThread already started");
                 return; // cannot start it again
@@ -157,7 +158,8 @@
             {
                 return;
             }
-            System.err.println("Starting ShutdownMonitorThread");
+            if (DEBUG)
+                System.err.println("Starting ShutdownMonitorThread");
             super.start();
         }
         
@@ -352,7 +354,9 @@
         {
             if (thread != null && thread.isAlive())
             {
-                System.err.printf("ShutdownMonitorThread already started");
+                // TODO why are we reentrant here?
+                if (DEBUG)
+                    System.err.printf("ShutdownMonitorThread already started");
                 return; // cannot start it again
             }
          
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/SslConnectionFactory.java b/jetty-server/src/main/java/org/eclipse/jetty/server/SslConnectionFactory.java
index da83f1f..d3e9fd6 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/SslConnectionFactory.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/SslConnectionFactory.java
@@ -78,6 +78,7 @@
         engine.setUseClientMode(false);
 
         SslConnection sslConnection = newSslConnection(connector, endPoint, engine);
+        sslConnection.setRenegotiationAllowed(_sslContextFactory.isRenegotiationAllowed());
         configure(sslConnection, connector, endPoint);
 
         ConnectionFactory next = connector.getConnectionFactory(_nextProtocol);
diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
index 4d15352..3d5fad4 100644
--- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
+++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java
@@ -65,6 +65,7 @@
 
 import org.eclipse.jetty.http.MimeTypes;
 import org.eclipse.jetty.server.ClassLoaderDump;
+import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.Dispatcher;
 import org.eclipse.jetty.server.Handler;
 import org.eclipse.jetty.server.HandlerContainer;
@@ -280,7 +281,8 @@
      *
      * @param vhosts
      *            Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be
-     *            String representation of IP addresses. Host names may start with '*.' to wildcard one level of names.
+     *            String representation of IP addresses. Host names may start with '*.' to wildcard one level of names.  Hosts may start with '@', in which case they
+     *            will match the {@link Connector#getName()} for the request.
      */
     public void setVirtualHosts(String[] vhosts)
     {
@@ -872,18 +874,29 @@
 
             boolean match = false;
 
-            for (int i = 0; !match && i < _vhosts.length; i++)
+            loop: for (String contextVhost:_vhosts)
             {
-                String contextVhost = _vhosts[i];
-                if (contextVhost == null)
+                if (contextVhost == null || contextVhost.length()==0)
                     continue;
-                if (contextVhost.startsWith("*."))
+                char c=contextVhost.charAt(0);
+                switch (c)
                 {
-                    // wildcard only at the beginning, and only for one additional subdomain level
-                    match = contextVhost.regionMatches(true,2,vhost,vhost.indexOf(".") + 1,contextVhost.length() - 2);
+                    case '*':
+                        if (contextVhost.startsWith("*."))
+                            // wildcard only at the beginning, and only for one additional subdomain level
+                            match = contextVhost.regionMatches(true,2,vhost,vhost.indexOf(".") + 1,contextVhost.length() - 2);
+                        break;
+                    case '@':
+                        String name=baseRequest.getHttpChannel().getConnector().getName();
+                        match=name!=null && contextVhost.length()==name.length()+1 && contextVhost.endsWith(name);
+                        break;
+                    default:
+                        match = contextVhost.equalsIgnoreCase(vhost);
                 }
-                else
-                    match = contextVhost.equalsIgnoreCase(vhost);
+                
+                if (match)
+                    break loop;
+                
             }
             if (!match)
                 return false;
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/LowResourcesMonitorTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/LowResourcesMonitorTest.java
index 365a85b..eac1057 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/LowResourcesMonitorTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/LowResourcesMonitorTest.java
@@ -80,13 +80,14 @@
     @Test
     public void testLowOnThreads() throws Exception
     {
+        Thread.sleep(1200);
         _threadPool.setMaxThreads(_threadPool.getThreads()-_threadPool.getIdleThreads()+10);
         Thread.sleep(1200);
         Assert.assertFalse(_lowResourcesMonitor.isLowOnResources());
         
         final CountDownLatch latch = new CountDownLatch(1);
         
-        for (int i=0;i<20;i++)
+        for (int i=0;i<100;i++)
         {
             _threadPool.dispatch(new Runnable()
             {
@@ -110,7 +111,6 @@
         
         latch.countDown();
         Thread.sleep(1200);
-        System.err.println(_threadPool.dump());
         Assert.assertFalse(_lowResourcesMonitor.isLowOnResources());      
     }
     
diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java
index b8fe723..f9d07f4 100644
--- a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java
+++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java
@@ -118,6 +118,79 @@
         }
 
     }
+    
+    
+    @Test
+    public void testNamedConnector() throws Exception
+    {
+        Server server = new Server();
+        LocalConnector connector = new LocalConnector(server);
+        LocalConnector connectorN = new LocalConnector(server);
+        connectorN.setName("name");
+        server.setConnectors(new Connector[] { connector, connectorN });
+
+        ContextHandler contextA = new ContextHandler("/");
+        contextA.setVirtualHosts(new String[]{"www.example.com" });
+        IsHandledHandler handlerA = new IsHandledHandler();
+        contextA.setHandler(handlerA);
+
+        ContextHandler contextB = new ContextHandler("/");
+        IsHandledHandler handlerB = new IsHandledHandler();
+        contextB.setHandler(handlerB);
+        contextB.setVirtualHosts(new String[]{ "@name" });
+
+        ContextHandler contextC = new ContextHandler("/");
+        IsHandledHandler handlerC = new IsHandledHandler();
+        contextC.setHandler(handlerC);
+
+        HandlerCollection c = new HandlerCollection();
+        c.addHandler(contextA);
+        c.addHandler(contextB);
+        c.addHandler(contextC);
+        server.setHandler(c);
+
+        server.start();
+        try
+        {
+            connector.getResponses("GET / HTTP/1.0\n" + "Host: www.example.com.\n\n");
+            assertTrue(handlerA.isHandled());
+            assertFalse(handlerB.isHandled());
+            assertFalse(handlerC.isHandled());
+            handlerA.reset();
+            handlerB.reset();
+            handlerC.reset();
+
+            connector.getResponses("GET / HTTP/1.0\n" + "Host: localhost\n\n");
+            assertFalse(handlerA.isHandled());
+            assertFalse(handlerB.isHandled());
+            assertTrue(handlerC.isHandled());
+            handlerA.reset();
+            handlerB.reset();
+            handlerC.reset();
+
+            connectorN.getResponses("GET / HTTP/1.0\n" + "Host: www.example.com.\n\n");
+            assertTrue(handlerA.isHandled());
+            assertFalse(handlerB.isHandled());
+            assertFalse(handlerC.isHandled());
+            handlerA.reset();
+            handlerB.reset();
+            handlerC.reset();
+
+            connectorN.getResponses("GET / HTTP/1.0\n" + "Host: localhost\n\n");
+            assertFalse(handlerA.isHandled());
+            assertTrue(handlerB.isHandled());
+            assertFalse(handlerC.isHandled());
+            handlerA.reset();
+            handlerB.reset();
+            handlerC.reset();
+
+        }
+        finally
+        {
+            server.stop();
+        }
+
+    }
 
     @Test
     public void testContextGetContext() throws Exception
diff --git a/jetty-servlet/pom.xml b/jetty-servlet/pom.xml
index bcc92b2..552e4b2 100644
--- a/jetty-servlet/pom.xml
+++ b/jetty-servlet/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <artifactId>jetty-project</artifactId>
     <groupId>org.eclipse.jetty</groupId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-servlet</artifactId>
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
index 0d67bb3..f95a58d 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/DefaultServlet.java
@@ -434,7 +434,7 @@
                 if (resource!=null && resource.exists() && !resource.isDirectory())
                 {
                     // Tell caches that response may vary by accept-encoding
-                    response.setHeader(HttpHeader.VARY.asString(),HttpHeader.ACCEPT_ENCODING.asString());
+                    response.addHeader(HttpHeader.VARY.asString(),HttpHeader.ACCEPT_ENCODING.asString());
                     
                     // Does the client accept gzip?
                     String accept=request.getHeader(HttpHeader.ACCEPT_ENCODING.asString());
diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
index 6de3b7e..1e50dd1 100644
--- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
+++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletHolder.java
@@ -71,7 +71,7 @@
     private static final Logger LOG = Log.getLogger(ServletHolder.class);
 
     /* ---------------------------------------------------------------- */
-    private int _initOrder;
+    private int _initOrder = -1;
     private boolean _initOnStartup=false;
     private Map<String, String> _roleMap;
     private String _forcedPath;
@@ -179,7 +179,7 @@
      */
     public void setInitOrder(int order)
     {
-        _initOnStartup=order>0;
+        _initOnStartup=order>=0;
         _initOrder = order;
     }
 
@@ -329,7 +329,6 @@
     throws Exception
     {
         super.initialize();
-        
         if (_extInstance || _initOnStartup)
         {
             try
diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
index 4c06368..b923e53 100644
--- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
+++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletContextHandlerTest.java
@@ -130,8 +130,8 @@
         
         holder0.setInitOrder(0);
         _server.start();
-        assertEquals(2,__testServlets.get());
-        assertThat(holder0.getServletInstance(),nullValue());
+        assertEquals(3,__testServlets.get());
+        assertThat(holder0.getServletInstance(),notNullValue(Servlet.class));
         _server.stop();
         assertEquals(0,__testServlets.get());
         
diff --git a/jetty-servlets/pom.xml b/jetty-servlets/pom.xml
index b1e1f36..0e0f464 100644
--- a/jetty-servlets/pom.xml
+++ b/jetty-servlets/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <artifactId>jetty-project</artifactId>
     <groupId>org.eclipse.jetty</groupId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-servlets</artifactId>
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/IncludableGzipFilter.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/IncludableGzipFilter.java
index 1cb6d10..4469034 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/IncludableGzipFilter.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/IncludableGzipFilter.java
@@ -84,15 +84,6 @@
                         {
                             return null;
                         }
-
-                        @Override
-                        protected void setHeader(String name, String value)
-                        {
-                            super.setHeader(name, value);
-                            HttpServletResponse response = (HttpServletResponse)getResponse();
-                            if (!response.containsHeader(name))
-                                response.setHeader("org.eclipse.jetty.server.include." + name, value);
-                        }
                     };
                 }
             };
@@ -111,15 +102,6 @@
                         {
                             return new GZIPOutputStream(_response.getOutputStream(),_bufferSize);
                         }
-
-                        @Override
-                        protected void setHeader(String name, String value)
-                        {
-                            super.setHeader(name, value);
-                            HttpServletResponse response = (HttpServletResponse)getResponse();
-                            if (!response.containsHeader(name))
-                                response.setHeader("org.eclipse.jetty.server.include." + name, value);
-                        }
                     };
                 }
             };
@@ -138,15 +120,6 @@
                         {
                             return new DeflaterOutputStream(_response.getOutputStream(),new Deflater(_deflateCompressionLevel, _deflateNoWrap));
                         }
-
-                        @Override
-                        protected void setHeader(String name, String value)
-                        {
-                            super.setHeader(name, value);
-                            HttpServletResponse response = (HttpServletResponse)getResponse();
-                            if (!response.containsHeader(name))
-                                response.setHeader("org.eclipse.jetty.server.include." + name, value);
-                        }
                     };
                 }
             };
@@ -176,6 +149,16 @@
             if (!response.containsHeader(name))
                 response.setHeader("org.eclipse.jetty.server.include."+name,value);
         }
+
+        @Override
+        public void addHeader(String name, String value)
+        {
+            super.addHeader(name, value);
+            HttpServletResponse response = (HttpServletResponse)getResponse();
+            if (!response.containsHeader(name))
+                setHeader(name,value);
+        }
+        
         @Override
         protected PrintWriter newWriter(OutputStream out, String encoding) throws UnsupportedEncodingException
         {
diff --git a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/AbstractCompressedStream.java b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/AbstractCompressedStream.java
index bd10743..60456a5 100644
--- a/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/AbstractCompressedStream.java
+++ b/jetty-servlets/src/main/java/org/eclipse/jetty/servlets/gzip/AbstractCompressedStream.java
@@ -235,7 +235,7 @@
             setHeader("Content-Encoding", _encoding);
                 if (_response.containsHeader("Content-Encoding"))
                 {
-                    setHeader("Vary",_vary);
+                    addHeader("Vary",_vary);
                     _out=_compressedOutputStream=createStream();
                     if (_out!=null)
                     {
@@ -270,7 +270,7 @@
         if (_out == null || _bOut != null)
         {
             if (sendVary)
-                setHeader("Vary",_vary);
+                addHeader("Vary",_vary);
             if (_wrapper.getETag()!=null)
                 setHeader("ETag",_wrapper.getETag());
                 
@@ -342,6 +342,11 @@
         return encoding == null?new PrintWriter(out):new PrintWriter(new OutputStreamWriter(out,encoding));
     }
 
+    protected void addHeader(String name,String value)
+    {
+        _response.addHeader(name, value);
+    }
+
     protected void setHeader(String name,String value)
     {
         _response.setHeader(name, value);
diff --git a/jetty-spdy/pom.xml b/jetty-spdy/pom.xml
index 0a23721..7b3020b 100644
--- a/jetty-spdy/pom.xml
+++ b/jetty-spdy/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.eclipse.jetty</groupId>
         <artifactId>jetty-project</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-spdy/spdy-client/pom.xml b/jetty-spdy/spdy-client/pom.xml
index 30609a1..9bb89ae 100644
--- a/jetty-spdy/spdy-client/pom.xml
+++ b/jetty-spdy/spdy-client/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.eclipse.jetty.spdy</groupId>
         <artifactId>spdy-parent</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java
index 2a23c5f..2456a22 100644
--- a/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java
+++ b/jetty-spdy/spdy-client/src/main/java/org/eclipse/jetty/spdy/client/SPDYClient.java
@@ -307,6 +307,7 @@
                     {
                         final SSLEngine engine = client.newSSLEngine(sslContextFactory, channel);
                         SslConnection sslConnection = new SslConnection(bufferPool, getExecutor(), endPoint, engine);
+                        sslConnection.setRenegotiationAllowed(sslContextFactory.isRenegotiationAllowed());
                         DecryptedEndPoint sslEndPoint = sslConnection.getDecryptedEndPoint();
                         NextProtoNegoClientConnection connection = new NextProtoNegoClientConnection(channel, sslEndPoint, attachment, getExecutor(), client);
                         sslEndPoint.setConnection(connection);
diff --git a/jetty-spdy/spdy-core/pom.xml b/jetty-spdy/spdy-core/pom.xml
index 520c592..3bd7e71 100644
--- a/jetty-spdy/spdy-core/pom.xml
+++ b/jetty-spdy/spdy-core/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.eclipse.jetty.spdy</groupId>
         <artifactId>spdy-parent</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
index c642050..a0bda51 100644
--- a/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
+++ b/jetty-spdy/spdy-core/src/main/java/org/eclipse/jetty/spdy/StandardSession.java
@@ -110,7 +110,9 @@
     private final AtomicBoolean goAwaySent = new AtomicBoolean();
     private final AtomicBoolean goAwayReceived = new AtomicBoolean();
     private final AtomicInteger lastStreamId = new AtomicInteger();
+    private final AtomicInteger localStreamCount = new AtomicInteger(0);
     private final FlowControlStrategy flowControlStrategy;
+    private volatile int maxConcurrentLocalStreams = -1;
     private boolean flushing;
     private Throwable failure;
 
@@ -181,6 +183,8 @@
             // TODO: for SPDYv3 we need to support the "slot" argument
             SynStreamFrame synStream = new SynStreamFrame(version, synInfo.getFlags(), streamId, associatedStreamId, synInfo.getPriority(), (short)0, synInfo.getHeaders());
             IStream stream = createStream(synStream, listener, true, promise);
+            if (stream == null)
+                return;
             generateAndEnqueueControlFrame(stream, synStream, synInfo.getTimeout(), synInfo.getUnit(), stream);
         }
         flush();
@@ -535,15 +539,39 @@
         }
 
         int streamId = stream.getId();
+
+        if (local)
+        {
+            while (true)
+            {
+                int oldStreamCountValue = localStreamCount.get();
+                int maxConcurrentStreams = maxConcurrentLocalStreams;
+                if (maxConcurrentStreams > -1 && oldStreamCountValue >= maxConcurrentStreams)
+                {
+                    String msg = String.format("Max concurrent local streams (%d) exceeded.",
+                            maxConcurrentStreams);
+                    LOG.debug(msg);
+                    promise.failed(new SPDYException(msg));
+                    return null;
+                }
+                if (localStreamCount.compareAndSet(oldStreamCountValue, oldStreamCountValue + 1))
+                    break;
+            }
+        }
+
         if (streams.putIfAbsent(streamId, stream) != null)
         {
+            //TODO: fail promise
             if (local)
+            {
+                localStreamCount.decrementAndGet();
                 throw new IllegalStateException("Duplicate stream id " + streamId);
+            }
             RstInfo rstInfo = new RstInfo(streamId, StreamStatus.PROTOCOL_ERROR);
             LOG.debug("Duplicate stream, {}", rstInfo);
             try
             {
-                rst(rstInfo);
+                rst(rstInfo); //TODO: non blocking reset or find the reason why blocking is used
             }
             catch (InterruptedException | ExecutionException | TimeoutException e)
             {
@@ -554,8 +582,7 @@
         else
         {
             LOG.debug("Created {}", stream);
-            if (local)
-                notifyStreamCreated(stream);
+            notifyStreamCreated(stream);
             return stream;
         }
     }
@@ -590,10 +617,15 @@
 
         IStream removed = streams.remove(stream.getId());
         if (removed != null)
+        {
             assert removed == stream;
 
-        LOG.debug("Removed {}", stream);
-        notifyStreamClosed(stream);
+            if (streamIds.get() % 2 == stream.getId() % 2)
+                localStreamCount.decrementAndGet();
+
+            LOG.debug("Removed {}", stream);
+            notifyStreamClosed(stream);
+        }
     }
 
     private void notifyStreamClosed(IStream stream)
@@ -666,6 +698,13 @@
             setWindowSize(windowSize);
             LOG.debug("Updated session window size to {}", windowSize);
         }
+        Settings.Setting maxConcurrentStreamsSetting = frame.getSettings().get(Settings.ID.MAX_CONCURRENT_STREAMS);
+        if (maxConcurrentStreamsSetting != null)
+        {
+            int maxConcurrentStreamsValue = maxConcurrentStreamsSetting.value();
+            maxConcurrentLocalStreams = maxConcurrentStreamsValue;
+            LOG.debug("Updated session maxConcurrentLocalStreams to {}", maxConcurrentStreamsValue);
+        }
         SettingsInfo settingsInfo = new SettingsInfo(frame.getSettings(), frame.isClearPersisted());
         notifyOnSettings(listener, settingsInfo);
         flush();
diff --git a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java
index 44e56ff..813fb0c 100644
--- a/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java
+++ b/jetty-spdy/spdy-core/src/test/java/org/eclipse/jetty/spdy/StandardSessionTest.java
@@ -18,15 +18,6 @@
 
 package org.eclipse.jetty.spdy;
 
-import static org.hamcrest.Matchers.greaterThan;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-
 import java.nio.ByteBuffer;
 import java.nio.channels.ClosedChannelException;
 import java.util.HashSet;
@@ -47,12 +38,14 @@
 import org.eclipse.jetty.spdy.api.RstInfo;
 import org.eclipse.jetty.spdy.api.SPDY;
 import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.Settings;
 import org.eclipse.jetty.spdy.api.Stream;
 import org.eclipse.jetty.spdy.api.StreamFrameListener;
 import org.eclipse.jetty.spdy.api.StreamStatus;
 import org.eclipse.jetty.spdy.api.StringDataInfo;
 import org.eclipse.jetty.spdy.api.SynInfo;
 import org.eclipse.jetty.spdy.frames.DataFrame;
+import org.eclipse.jetty.spdy.frames.SettingsFrame;
 import org.eclipse.jetty.spdy.frames.SynReplyFrame;
 import org.eclipse.jetty.spdy.frames.SynStreamFrame;
 import org.eclipse.jetty.spdy.generator.Generator;
@@ -74,6 +67,15 @@
 import org.mockito.runners.MockitoJUnitRunner;
 import org.mockito.stubbing.Answer;
 
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertThat;
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
 @RunWith(MockitoJUnitRunner.class)
 public class StandardSessionTest
 {
@@ -457,7 +459,30 @@
         stream.headers(new HeadersInfo(headers, true));
 
         verify(controller, times(3)).write(any(ByteBuffer.class), any(Callback.class));
+    }
 
+    @Test
+    public void testMaxConcurrentStreams() throws InterruptedException
+    {
+        final CountDownLatch failedBecauseMaxConcurrentStreamsExceeded = new CountDownLatch(1);
+
+        Settings settings = new Settings();
+        settings.put(new Settings.Setting(Settings.ID.MAX_CONCURRENT_STREAMS, 0));
+        SettingsFrame settingsFrame = new SettingsFrame(VERSION, (byte)0, settings);
+        session.onControlFrame(settingsFrame);
+
+        PushSynInfo pushSynInfo = new PushSynInfo(1, new PushInfo(new Fields(), false));
+        session.syn(pushSynInfo, null, new Promise.Adapter<Stream>()
+        {
+            @Override
+            public void failed(Throwable x)
+            {
+                failedBecauseMaxConcurrentStreamsExceeded.countDown();
+            }
+        });
+
+        assertThat("Opening push stream failed because maxConcurrentStream is exceeded",
+                failedBecauseMaxConcurrentStreamsExceeded.await(5, TimeUnit.SECONDS), is(true));
     }
 
     @Test
diff --git a/jetty-spdy/spdy-example-webapp/pom.xml b/jetty-spdy/spdy-example-webapp/pom.xml
index 33bc39a..37830b2 100644
--- a/jetty-spdy/spdy-example-webapp/pom.xml
+++ b/jetty-spdy/spdy-example-webapp/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.eclipse.jetty.spdy</groupId>
         <artifactId>spdy-parent</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>spdy-example-webapp</artifactId>
diff --git a/jetty-spdy/spdy-http-server/pom.xml b/jetty-spdy/spdy-http-server/pom.xml
index a130ca4..c3ec31e 100644
--- a/jetty-spdy/spdy-http-server/pom.xml
+++ b/jetty-spdy/spdy-http-server/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.eclipse.jetty.spdy</groupId>
         <artifactId>spdy-parent</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>spdy-http-server</artifactId>
diff --git a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java
index f52c875..099f736 100644
--- a/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java
+++ b/jetty-spdy/spdy-http-server/src/test/java/org/eclipse/jetty/spdy/server/http/ReferrerPushStrategyTest.java
@@ -101,14 +101,14 @@
     @Test
     public void testPushHeadersAreValid() throws Exception
     {
-        sendMainRequestAndCSSRequest();
+        sendMainRequestAndCSSRequest(null);
         run2ndClientRequests(true, true);
     }
 
     @Test
     public void testClientResetsPushStreams() throws Exception
     {
-        sendMainRequestAndCSSRequest();
+        sendMainRequestAndCSSRequest(null);
         final CountDownLatch pushDataLatch = new CountDownLatch(1);
         final CountDownLatch pushSynHeadersValid = new CountDownLatch(1);
         Session session = startClient(version, serverAddress, null);
@@ -125,14 +125,14 @@
     public void testUserAgentBlackList() throws Exception
     {
         pushStrategy.setUserAgentBlacklist(Arrays.asList(".*(?i)firefox/16.*"));
-        sendMainRequestAndCSSRequest();
+        sendMainRequestAndCSSRequest(null);
         run2ndClientRequests(false, false);
     }
 
     @Test
     public void testReferrerPushPeriod() throws Exception
     {
-        Session session = sendMainRequestAndCSSRequest();
+        Session session = sendMainRequestAndCSSRequest(null);
 
         // Sleep for pushPeriod This should prevent application.js from being mapped as pushResource
         Thread.sleep(referrerPushPeriod + 1);
@@ -148,13 +148,38 @@
         connector.addConnectionFactory(defaultFactory);
         connector.setDefaultProtocol(defaultFactory.getProtocol()); // TODO I don't think this is right
 
-        Session session = sendMainRequestAndCSSRequest();
+        Session session = sendMainRequestAndCSSRequest(null);
 
         sendRequest(session, associatedJSRequestHeaders, null, null);
 
         run2ndClientRequests(false, true);
     }
 
+    @Test
+    public void testMaxConcurrentStreamsToDisablePush() throws Exception
+    {
+        final CountDownLatch pushReceivedLatch = new CountDownLatch(1);
+        Session session = sendMainRequestAndCSSRequest(new SessionFrameListener.Adapter()
+        {
+            @Override
+            public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+            {
+                pushReceivedLatch.countDown();
+                return null;
+            }
+        });
+
+//        Settings settings = new Settings();
+//        settings.put(new Settings.Setting(Settings.ID.MAX_CONCURRENT_STREAMS, 0));
+//        SettingsInfo settingsInfo = new SettingsInfo(settings);
+//
+//        session.settings(settingsInfo);
+
+        sendRequest(session, mainRequestHeaders, null, null);
+
+        assertThat(pushReceivedLatch.await(1, TimeUnit.SECONDS), is(false));
+    }
+
     private InetSocketAddress createServer() throws Exception
     {
         GzipHandler gzipHandler = new GzipHandler();
@@ -177,9 +202,9 @@
         return startHTTPServer(version, gzipHandler);
     }
 
-    private Session sendMainRequestAndCSSRequest() throws Exception
+    private Session sendMainRequestAndCSSRequest(SessionFrameListener sessionFrameListener) throws Exception
     {
-        Session session = startClient(version, serverAddress, null);
+        Session session = startClient(version, serverAddress, sessionFrameListener);
 
         sendRequest(session, mainRequestHeaders, null, null);
         sendRequest(session, associatedCSSRequestHeaders, null, null);
@@ -197,7 +222,8 @@
             @Override
             public StreamFrameListener onPush(Stream stream, PushInfo pushInfo)
             {
-                validateHeaders(pushInfo.getHeaders(), pushSynHeadersValid);
+                if (pushSynHeadersValid != null)
+                    validateHeaders(pushInfo.getHeaders(), pushSynHeadersValid);
 
                 assertThat("Stream is unidirectional", stream.isUnidirectional(), is(true));
                 assertThat("URI header ends with css", pushInfo.getHeaders().get(HTTPSPDYHeader.URI.name(version))
diff --git a/jetty-spdy/spdy-server/pom.xml b/jetty-spdy/spdy-server/pom.xml
index 9d7be56..0bd4ca8 100644
--- a/jetty-spdy/spdy-server/pom.xml
+++ b/jetty-spdy/spdy-server/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.eclipse.jetty.spdy</groupId>
         <artifactId>spdy-parent</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/AbstractTest.java b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/AbstractTest.java
index 08625cc..cdbe2ba 100644
--- a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/AbstractTest.java
+++ b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/AbstractTest.java
@@ -53,13 +53,15 @@
         }
     };
 
+    protected final short version = SPDY.V2;
+
     protected Server server;
     protected SPDYClient.Factory clientFactory;
     protected SPDYServerConnector connector;
 
     protected InetSocketAddress startServer(ServerSessionFrameListener listener) throws Exception
     {
-        return startServer(SPDY.V2, listener);
+        return startServer(version, listener);
     }
 
     protected InetSocketAddress startServer(short version, ServerSessionFrameListener listener) throws Exception
@@ -99,7 +101,7 @@
 
     protected Session startClient(InetSocketAddress socketAddress, SessionFrameListener listener) throws Exception
     {
-        return startClient(SPDY.V2, socketAddress, listener);
+        return startClient(version, socketAddress, listener);
     }
 
     protected Session startClient(short version, InetSocketAddress socketAddress, SessionFrameListener listener) throws Exception
diff --git a/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/MaxConcurrentStreamTest.java b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/MaxConcurrentStreamTest.java
new file mode 100644
index 0000000..5c74ca3
--- /dev/null
+++ b/jetty-spdy/spdy-server/src/test/java/org/eclipse/jetty/spdy/server/MaxConcurrentStreamTest.java
@@ -0,0 +1,120 @@
+//
+//  ========================================================================
+//  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.spdy.server;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import org.eclipse.jetty.spdy.api.ByteBufferDataInfo;
+import org.eclipse.jetty.spdy.api.DataInfo;
+import org.eclipse.jetty.spdy.api.ReplyInfo;
+import org.eclipse.jetty.spdy.api.Session;
+import org.eclipse.jetty.spdy.api.SessionFrameListener;
+import org.eclipse.jetty.spdy.api.Settings;
+import org.eclipse.jetty.spdy.api.SettingsInfo;
+import org.eclipse.jetty.spdy.api.Stream;
+import org.eclipse.jetty.spdy.api.StreamFrameListener;
+import org.eclipse.jetty.spdy.api.SynInfo;
+import org.eclipse.jetty.spdy.api.server.ServerSessionFrameListener;
+import org.eclipse.jetty.util.BufferUtil;
+import org.eclipse.jetty.util.Fields;
+import org.junit.Test;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class MaxConcurrentStreamTest extends AbstractTest
+{
+    @Test
+    public void testMaxConcurrentStreamsSetByServer() throws Exception, ExecutionException
+    {
+        final CountDownLatch settingsReceivedLatch = new CountDownLatch(1);
+        final CountDownLatch dataReceivedLatch = new CountDownLatch(1);
+
+        Session session = startClient(startServer(new ServerSessionFrameListener.Adapter()
+        {
+            @Override
+            public void onConnect(Session session)
+            {
+                Settings settings = new Settings();
+                settings.put(new Settings.Setting(Settings.ID.MAX_CONCURRENT_STREAMS, 1));
+                try
+                {
+                    session.settings(new SettingsInfo(settings));
+                }
+                catch (ExecutionException | InterruptedException | TimeoutException e)
+                {
+                    e.printStackTrace();
+                }
+            }
+
+            @Override
+            public StreamFrameListener onSyn(Stream stream, SynInfo synInfo)
+            {
+                try
+                {
+                    stream.reply(new ReplyInfo(true));
+                }
+                catch (ExecutionException | InterruptedException | TimeoutException e)
+                {
+                    e.printStackTrace();
+                }
+                return new StreamFrameListener.Adapter()
+                {
+                    @Override
+                    public void onData(Stream stream, DataInfo dataInfo)
+                    {
+                        dataReceivedLatch.countDown();
+                    }
+                };
+            }
+        }), new SessionFrameListener.Adapter()
+        {
+            @Override
+            public void onSettings(Session session, SettingsInfo settingsInfo)
+            {
+                settingsReceivedLatch.countDown();
+            }
+        });
+
+        assertThat("Settings frame received", settingsReceivedLatch.await(5, TimeUnit.SECONDS), is(true));
+
+        SynInfo synInfo = new SynInfo(new Fields(), false);
+        Stream stream = session.syn(synInfo, null);
+
+        boolean failed = false;
+        try
+        {
+            session.syn(synInfo, null);
+        }
+        catch (ExecutionException | InterruptedException | TimeoutException e)
+        {
+            failed = true;
+        }
+
+        assertThat("Opening second stream failed", failed, is(true));
+
+        stream.data(new ByteBufferDataInfo(BufferUtil.EMPTY_BUFFER, true));
+        assertThat("Data has been received on first stream.", dataReceivedLatch.await(5, TimeUnit.SECONDS), is(true));
+
+        session.syn(synInfo, null);
+    }
+}
diff --git a/jetty-spring/pom.xml b/jetty-spring/pom.xml
index d2ec7c5..97e3aa4 100644
--- a/jetty-spring/pom.xml
+++ b/jetty-spring/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-spring</artifactId>
diff --git a/jetty-start/pom.xml b/jetty-start/pom.xml
index 4a4ac6a..240d08c 100644
--- a/jetty-start/pom.xml
+++ b/jetty-start/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-start</artifactId>
diff --git a/jetty-util-ajax/pom.xml b/jetty-util-ajax/pom.xml
index 9b0a2be..247bfd2 100644
--- a/jetty-util-ajax/pom.xml
+++ b/jetty-util-ajax/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-util-ajax</artifactId>
diff --git a/jetty-util/pom.xml b/jetty-util/pom.xml
index a9b1a2f..01bf1fb 100644
--- a/jetty-util/pom.xml
+++ b/jetty-util/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-util</artifactId>
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/AbstractTrie.java b/jetty-util/src/main/java/org/eclipse/jetty/util/AbstractTrie.java
index dd2f53c..a9cb827 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/AbstractTrie.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/AbstractTrie.java
@@ -57,16 +57,6 @@
         return get(s,0,s.length());
     }
 
-
-    @Override
-    public V get(ByteBuffer b, int offset, int len)
-    {
-        b=b.duplicate();
-        b.position(b.position()+offset);
-        b.limit(b.position()+len);
-        return get(BufferUtil.toString(b,StringUtil.__ISO_8859_1_CHARSET));
-    }
-
     @Override
     public V get(ByteBuffer b)
     {
@@ -86,15 +76,6 @@
     }
 
     @Override
-    public V getBest(ByteBuffer b, int offset, int len)
-    {
-        b=b.duplicate();
-        b.position(b.position()+offset);
-        b.limit(b.position()+len);
-        return getBest(BufferUtil.toString(b,StringUtil.__ISO_8859_1_CHARSET));
-    }
-
-    @Override
     public boolean isCaseInsensitive()
     {
         return _caseInsensitive;
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayTernaryTrie.java b/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayTernaryTrie.java
index 7c92ac5..312bd96 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayTernaryTrie.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/ArrayTernaryTrie.java
@@ -18,6 +18,7 @@
 
 package org.eclipse.jetty.util;
 
+import java.nio.ByteBuffer;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -194,6 +195,45 @@
     }
 
     
+    @Override
+    public V get(ByteBuffer b, int offset, int length)
+    {
+        int t = _tree[EQ];
+        int len = length;
+        int i=0;
+        offset+=b.position();
+        
+        while(i<len)
+        {
+            byte c=(byte)(b.get(offset+i++)&0x7f);
+            if(isCaseInsensitive())
+                c=(byte)StringUtil.lowercases[c];
+            
+            while (true)
+            {
+                int row = ROW_SIZE*t;
+                char n=_tree[row];
+                int diff=n-c;
+                
+                if (diff==0)
+                {
+                    if (i==len)
+                        return (V)_value[t];
+                    t=_tree[row+EQ];
+                    if (t==0)
+                        return null;
+                    break;
+                }
+
+                t=_tree[row+((diff<0)?LO:HI)];
+                if (t==0)
+                    return null;
+            }
+        }
+        
+        return null;
+    }
+
     /* ------------------------------------------------------------ */
     @Override
     public V getBest(String s)
@@ -248,6 +288,95 @@
     }
 
 
+    /* ------------------------------------------------------------ */
+    @Override
+    public V getBest(ByteBuffer b, int offset, int len)
+    {
+        if (b.hasArray())
+            return getBest(_tree[EQ],b.array(),b.arrayOffset()+b.position()+offset,len);
+        return getBest(_tree[EQ],b,offset,len);
+    }
+
+    /* ------------------------------------------------------------ */
+    private V getBest(int t,byte[] b, int offset, int len)
+    {
+        int node=0;
+        for(int i=0; t!=0 && i<len; i++)
+        {
+            byte c=(byte)(b[offset+i]&0x7f);
+            if(isCaseInsensitive())
+                c=(byte)StringUtil.lowercases[c];
+
+            while (t!=0)
+            {
+                int row = ROW_SIZE*t;
+                char n=_tree[row];
+                int diff=n-c;
+                
+                if (diff==0)
+                {
+                    node=t;
+                    t=_tree[row+EQ];
+                    
+                    // if this node is a match, recurse to remember 
+                    if (_key[node]!=null)
+                    {
+                        V best=getBest(t,b,offset+i+1,len-i-1);
+                        if (best!=null)
+                            return best;
+                        return (V)_value[node];
+                    }
+                    
+                    break;
+                }
+
+                t=_tree[row+((diff<0)?LO:HI)];
+            }
+        }
+        return null;
+    }
+
+    /* ------------------------------------------------------------ */
+    private V getBest(int t,ByteBuffer b, int offset, int len)
+    {
+        int node=0;
+        int o= offset+b.position();
+        
+        for(int i=0; t!=0 && i<len; i++)
+        {
+            byte c=(byte)(b.get(o+i)&0x7f);
+            if(isCaseInsensitive())
+                c=(byte)StringUtil.lowercases[c];
+
+            while (t!=0)
+            {
+                int row = ROW_SIZE*t;
+                char n=_tree[row];
+                int diff=n-c;
+                
+                if (diff==0)
+                {
+                    node=t;
+                    t=_tree[row+EQ];
+                    
+                    // if this node is a match, recurse to remember 
+                    if (_key[node]!=null)
+                    {
+                        V best=getBest(t,b,offset+i+1,len-i-1);
+                        if (best!=null)
+                            return best;
+                        return (V)_value[node];
+                    }
+                    
+                    break;
+                }
+
+                t=_tree[row+((diff<0)?LO:HI)];
+            }
+        }
+        return null;
+    }
+
     @Override
     public String toString()
     {
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java
index a9630e6..f80e5ab 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/resource/Resource.java
@@ -218,8 +218,7 @@
     {
         URL url=null;
         // Try to format as a URL?
-        ClassLoader
-            loader=Thread.currentThread().getContextClassLoader();
+        ClassLoader loader=Thread.currentThread().getContextClassLoader();
         if (loader!=null)
         {
             try
@@ -251,7 +250,7 @@
         {
             url=ClassLoader.getSystemResource(resource);
             if (url==null && resource.startsWith("/"))
-                url=loader.getResource(resource.substring(1));
+                url=ClassLoader.getSystemResource(resource.substring(1));
         }
         
         if (url==null)
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java b/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java
index 857d199..f0ff187 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/ssl/SslContextFactory.java
@@ -41,6 +41,9 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 import javax.net.ssl.CertPathTrustManagerParameters;
 import javax.net.ssl.KeyManager;
 import javax.net.ssl.KeyManagerFactory;
@@ -196,8 +199,12 @@
     /** EndpointIdentificationAlgorithm - when set to "HTTPS" hostname verification will be enabled */
     private String _endpointIdentificationAlgorithm = null;
 
+    /** Whether to blindly trust certificates */
     private boolean _trustAll;
 
+    /** Whether TLS renegotiation is allowed */
+    private boolean _renegotiationAllowed = true;
+
     /**
      * Construct an instance of SslContextFactory
      * Default constructor for use in XmlConfiguration files
@@ -369,6 +376,7 @@
     }
 
     /**
+     * You can either use the exact cipher suite name or a a regular expression.
      * @param cipherSuites
      *            The array of cipher suite names to exclude from
      *            {@link SSLEngine#setEnabledCipherSuites(String[])}
@@ -399,6 +407,7 @@
     }
 
     /**
+     * You can either use the exact cipher suite name or a a regular expression.
      * @param cipherSuites
      *            The array of cipher suite names to include in
      *            {@link SSLEngine#setEnabledCipherSuites(String[])}
@@ -760,6 +769,22 @@
     }
 
     /**
+     * @return whether TLS renegotiation is allowed (true by default)
+     */
+    public boolean isRenegotiationAllowed()
+    {
+        return _renegotiationAllowed;
+    }
+
+    /**
+     * @param renegotiationAllowed whether TLS renegotiation is allowed
+     */
+    public void setRenegotiationAllowed(boolean renegotiationAllowed)
+    {
+        _renegotiationAllowed = renegotiationAllowed;
+    }
+
+    /**
      * @return Path to file that contains Certificate Revocation List
      */
     public String getCrlPath()
@@ -1035,25 +1060,47 @@
      */
     public String[] selectCipherSuites(String[] enabledCipherSuites, String[] supportedCipherSuites)
     {
-        Set<String> selected_ciphers = new LinkedHashSet<>();
+        Set<String> selected_ciphers = new CopyOnWriteArraySet<>();
 
         // Set the starting ciphers - either from the included or enabled list
         if (_includeCipherSuites!=null)
-        {
-            // Use only the supported included ciphers
-            for (String cipherSuite : _includeCipherSuites)
-                if(Arrays.asList(supportedCipherSuites).contains(cipherSuite))
-                    selected_ciphers.add(cipherSuite);
-        }
+            processIncludeCipherSuites(supportedCipherSuites, selected_ciphers);
         else
             selected_ciphers.addAll(Arrays.asList(enabledCipherSuites));
 
+        removeExcludedCipherSuites(selected_ciphers);
 
-        // Remove any excluded ciphers
-        selected_ciphers.removeAll(_excludeCipherSuites);
         return selected_ciphers.toArray(new String[selected_ciphers.size()]);
     }
 
+    private void processIncludeCipherSuites(String[] supportedCipherSuites, Set<String> selected_ciphers)
+    {
+        for (String cipherSuite : _includeCipherSuites)
+        {
+            Pattern p = Pattern.compile(cipherSuite);
+            for (String supportedCipherSuite : supportedCipherSuites)
+            {
+                Matcher m = p.matcher(supportedCipherSuite);
+                if (m.matches())
+                    selected_ciphers.add(supportedCipherSuite);
+            }
+        }
+    }
+
+    private void removeExcludedCipherSuites(Set<String> selected_ciphers)
+    {
+        for (String excludeCipherSuite : _excludeCipherSuites)
+        {
+            Pattern excludeCipherPattern = Pattern.compile(excludeCipherSuite);
+            for (String selectedCipherSuite : selected_ciphers)
+            {
+                Matcher m = excludeCipherPattern.matcher(selectedCipherSuite);
+                if (m.matches())
+                    selected_ciphers.remove(selectedCipherSuite);
+            }
+        }
+    }
+
     /**
      * Check if the lifecycle has been started and throw runtime exception
      */
diff --git a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java
index dcfa977..4ffc802 100644
--- a/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java
+++ b/jetty-util/src/main/java/org/eclipse/jetty/util/thread/QueuedThreadPool.java
@@ -31,6 +31,7 @@
 import java.util.concurrent.atomic.AtomicLong;
 
 import org.eclipse.jetty.util.BlockingArrayQueue;
+import org.eclipse.jetty.util.ConcurrentArrayBlockingQueue;
 import org.eclipse.jetty.util.StringUtil;
 import org.eclipse.jetty.util.annotation.ManagedAttribute;
 import org.eclipse.jetty.util.annotation.ManagedObject;
@@ -91,7 +92,7 @@
         setStopTimeout(5000);
         
         if (queue==null)
-            queue=new BlockingArrayQueue<Runnable>(_minThreads, _minThreads);// TODO ConcurrentArrayBlockingQueue.Unbounded<Runnable>();
+            queue=new ConcurrentArrayBlockingQueue.Unbounded<Runnable>();
         _jobs=queue;
 
     }
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/QueueBenchmarkTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/QueueBenchmarkTest.java
new file mode 100644
index 0000000..8990102
--- /dev/null
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/QueueBenchmarkTest.java
@@ -0,0 +1,226 @@
+//
+//  ========================================================================
+//  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.util;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Queue;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+import java.util.concurrent.CyclicBarrier;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+import org.eclipse.jetty.toolchain.test.AdvancedRunner;
+import org.eclipse.jetty.toolchain.test.annotation.Slow;
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.junit.Assume;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+@Ignore
+@RunWith(AdvancedRunner.class)
+public class QueueBenchmarkTest
+{
+    private static final Logger logger = Log.getLogger(QueueBenchmarkTest.class);
+    private static final Runnable ELEMENT = new Runnable()
+    {
+        @Override
+        public void run()
+        {
+        }
+    };
+    private static final Runnable END = new Runnable()
+    {
+        @Override
+        public void run()
+        {
+        }
+    };
+
+    @Slow
+    @Test
+    public void testQueues() throws Exception
+    {
+        int cores = Runtime.getRuntime().availableProcessors();
+        Assume.assumeTrue(cores > 1);
+
+        final int readers = cores / 2;
+        final int writers = readers;
+        final int iterations = 16 * 1024 * 1024;
+
+        final List<Queue<Runnable>> queues = new ArrayList<>();
+        queues.add(new ConcurrentArrayQueue<Runnable>()); // Jetty lock-free queue, allocating array blocks
+        queues.add(new ConcurrentLinkedQueue<Runnable>()); // JDK lock-free queue, allocating nodes
+        queues.add(new ArrayBlockingQueue<Runnable>(iterations * writers)); // JDK lock-based, circular array queue
+        queues.add(new BlockingArrayQueue<Runnable>(iterations * writers)); // Jetty lock-based, circular array queue
+
+        testQueues(readers, writers, iterations, queues, false);
+    }
+
+    @Slow
+    @Test
+    public void testBlockingQueues() throws Exception
+    {
+        int cores = Runtime.getRuntime().availableProcessors();
+        Assume.assumeTrue(cores > 1);
+
+        final int readers = cores / 2;
+        final int writers = readers;
+        final int iterations = 16 * 1024 * 1024;
+
+        final List<Queue<Runnable>> queues = new ArrayList<>();
+        queues.add(new ConcurrentArrayBlockingQueue.Unbounded<Runnable>());
+        queues.add(new ConcurrentArrayBlockingQueue.Bounded<Runnable>(iterations * writers));
+        queues.add(new LinkedBlockingQueue<Runnable>());
+        queues.add(new ArrayBlockingQueue<Runnable>(iterations * writers));
+        queues.add(new BlockingArrayQueue<Runnable>(iterations * writers));
+
+        testQueues(readers, writers, iterations, queues, true);
+    }
+
+    private void testQueues(final int readers, final int writers, final int iterations, List<Queue<Runnable>> queues, final boolean blocking) throws Exception
+    {
+        final int runs = 8;
+        int threads = readers + writers;
+        final CyclicBarrier barrier = new CyclicBarrier(threads + 1);
+
+        for (final Queue<Runnable> queue : queues)
+        {
+            for (int r = 0; r < runs; ++r)
+            {
+                for (int i = 0; i < readers; ++i)
+                {
+                    Thread thread = new Thread()
+                    {
+                        @Override
+                        public void run()
+                        {
+                            await(barrier);
+                            consume(queue, writers, blocking);
+                            await(barrier);
+                        }
+                    };
+                    thread.start();
+                }
+                for (int i = 0; i < writers; ++i)
+                {
+                    Thread thread = new Thread()
+                    {
+                        @Override
+                        public void run()
+                        {
+                            await(barrier);
+                            produce(queue, readers, iterations);
+                            await(barrier);
+                        }
+                    };
+                    thread.start();
+                }
+
+                await(barrier);
+                long begin = System.nanoTime();
+                await(barrier);
+                long end = System.nanoTime();
+                long elapsed = TimeUnit.NANOSECONDS.toMillis(end - begin);
+                logger.info("{} Readers/Writers: {}/{} => {} ms", queue.getClass().getSimpleName(), readers, writers, elapsed);
+            }
+        }
+    }
+
+    private static void consume(Queue<Runnable> queue, int writers, boolean blocking)
+    {
+        while (true)
+        {
+            Runnable element = blocking ? take(queue) : poll(queue);
+            if (element == END)
+                if (--writers == 0)
+                    break;
+        }
+    }
+
+    private static void produce(Queue<Runnable> queue, int readers, int iterations)
+    {
+        for (int i = 0; i < iterations; ++i)
+            append(queue, ELEMENT);
+        for (int i = 0; i < readers; ++i)
+            append(queue, END);
+    }
+
+    private static void append(Queue<Runnable> queue, Runnable element)
+    {
+        if (!queue.offer(element))
+            logger.warn("Queue {} capacity is too small", queue);
+    }
+
+    private static Runnable take(Queue<Runnable> queue)
+    {
+        try
+        {
+            return ((BlockingQueue<Runnable>)queue).take();
+        }
+        catch (InterruptedException x)
+        {
+            throw new RuntimeException(x);
+        }
+    }
+
+    private static Runnable poll(Queue<Runnable> queue)
+    {
+        int loops = 0;
+        while (true)
+        {
+            Runnable element = queue.poll();
+            if (element != null)
+                return element;
+            // Busy loop
+            sleepMicros(1);
+            ++loops;
+            if (loops % 16 == 0)
+                logger.warn("Spin looping while polling empty queue: {} spins: ", loops);
+        }
+    }
+
+    private static void sleepMicros(long sleep)
+    {
+        try
+        {
+            TimeUnit.MICROSECONDS.sleep(sleep);
+        }
+        catch (InterruptedException x)
+        {
+            throw new RuntimeException(x);
+        }
+    }
+
+    private static void await(CyclicBarrier barrier)
+    {
+        try
+        {
+            barrier.await();
+        }
+        catch (Exception x)
+        {
+            throw new RuntimeException(x);
+        }
+    }
+}
diff --git a/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java b/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java
index 6122dfd..980640c 100644
--- a/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java
+++ b/jetty-util/src/test/java/org/eclipse/jetty/util/ssl/SslContextFactoryTest.java
@@ -18,15 +18,12 @@
 
 package org.eclipse.jetty.util.ssl;
 
-import static org.hamcrest.Matchers.equalTo;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.junit.Assert.assertTrue;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.security.KeyStore;
 
+import javax.net.ssl.SSLEngine;
+
 import org.eclipse.jetty.util.component.AbstractLifeCycle;
 import org.eclipse.jetty.util.log.Log;
 import org.eclipse.jetty.util.log.StdErrLog;
@@ -35,6 +32,12 @@
 import org.junit.Before;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.equalTo;
+import static org.hamcrest.Matchers.greaterThan;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
 
 public class SslContextFactoryTest
 {
@@ -190,6 +193,30 @@
     }
 
     @Test
+    public void testSetExcludeCipherSuitesRegex() throws Exception
+    {
+        cf.setExcludeCipherSuites(".*RC4.*");
+        cf.start();
+        SSLEngine sslEngine = cf.newSSLEngine();
+        String[] enabledCipherSuites = sslEngine.getEnabledCipherSuites();
+        assertThat("At least 1 cipherSuite is enabled", enabledCipherSuites.length, greaterThan(0));
+        for (String enabledCipherSuite : enabledCipherSuites)
+            assertThat("CipherSuite does not contain RC4", enabledCipherSuite.contains("RC4"), is(false));
+    }
+
+    @Test
+    public void testSetIncludeCipherSuitesRegex() throws Exception
+    {
+        cf.setIncludeCipherSuites(".*RC4.*");
+        cf.start();
+        SSLEngine sslEngine = cf.newSSLEngine();
+        String[] enabledCipherSuites = sslEngine.getEnabledCipherSuites();
+        assertThat("At least 1 cipherSuite is enabled", enabledCipherSuites.length, greaterThan(0));
+        for (String enabledCipherSuite : enabledCipherSuites)
+            assertThat("CipherSuite contains RC4", enabledCipherSuite.contains("RC4"), is(true));
+    }
+
+    @Test
     public void testSetIncludeCipherSuitesPreservesOrder()
     {
         String[] supportedCipherSuites = new String[]{"cipher4", "cipher2", "cipher1", "cipher3"};
diff --git a/jetty-webapp/pom.xml b/jetty-webapp/pom.xml
index a1c8e4e..f397e92 100644
--- a/jetty-webapp/pom.xml
+++ b/jetty-webapp/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-webapp</artifactId>
diff --git a/jetty-websocket/pom.xml b/jetty-websocket/pom.xml
index 701c7ec..8633efc 100644
--- a/jetty-websocket/pom.xml
+++ b/jetty-websocket/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <artifactId>jetty-project</artifactId>
         <groupId>org.eclipse.jetty</groupId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/websocket-api/pom.xml b/jetty-websocket/websocket-api/pom.xml
index 5dceaec..f850046 100644
--- a/jetty-websocket/websocket-api/pom.xml
+++ b/jetty-websocket/websocket-api/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.eclipse.jetty.websocket</groupId>
         <artifactId>websocket-parent</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/websocket-client/pom.xml b/jetty-websocket/websocket-client/pom.xml
index b06b251..ae00946 100644
--- a/jetty-websocket/websocket-client/pom.xml
+++ b/jetty-websocket/websocket-client/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.eclipse.jetty.websocket</groupId>
         <artifactId>websocket-parent</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java
index 21c7695..e3f1669 100644
--- a/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java
+++ b/jetty-websocket/websocket-client/src/main/java/org/eclipse/jetty/websocket/client/io/WebSocketClientSelectorManager.java
@@ -22,7 +22,6 @@
 import java.nio.channels.SelectionKey;
 import java.nio.channels.SocketChannel;
 import java.util.concurrent.Executor;
-
 import javax.net.ssl.SSLEngine;
 
 import org.eclipse.jetty.io.ByteBufferPool;
@@ -82,6 +81,7 @@
                 {
                     SSLEngine engine = newSSLEngine(sslContextFactory,channel);
                     SslConnection sslConnection = new SslConnection(bufferPool,getExecutor(),endPoint,engine);
+                    sslConnection.setRenegotiationAllowed(sslContextFactory.isRenegotiationAllowed());
                     EndPoint sslEndPoint = sslConnection.getDecryptedEndPoint();
 
                     Connection connection = newUpgradeConnection(channel,sslEndPoint,connectPromise);
diff --git a/jetty-websocket/websocket-common/pom.xml b/jetty-websocket/websocket-common/pom.xml
index aec3c95..eb05238 100644
--- a/jetty-websocket/websocket-common/pom.xml
+++ b/jetty-websocket/websocket-common/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <groupId>org.eclipse.jetty.websocket</groupId>
     <artifactId>websocket-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
 
   <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/websocket-server/pom.xml b/jetty-websocket/websocket-server/pom.xml
index 45b533e..25b9506 100644
--- a/jetty-websocket/websocket-server/pom.xml
+++ b/jetty-websocket/websocket-server/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.eclipse.jetty.websocket</groupId>
         <artifactId>websocket-parent</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java
index cb2770d..b7e80d3 100644
--- a/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java
+++ b/jetty-websocket/websocket-server/src/test/java/org/eclipse/jetty/websocket/server/WebSocketCloseTest.java
@@ -18,8 +18,6 @@
 
 package org.eclipse.jetty.websocket.server;
 
-import static org.hamcrest.Matchers.*;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
@@ -45,11 +43,15 @@
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
+import org.junit.Ignore;
 import org.junit.Test;
 
+import static org.hamcrest.Matchers.is;
+
 /**
  * Tests various close scenarios
  */
+@Ignore
 public class WebSocketCloseTest
 {
     @SuppressWarnings("serial")
diff --git a/jetty-websocket/websocket-servlet/pom.xml b/jetty-websocket/websocket-servlet/pom.xml
index a9154bb..826b5cc 100644
--- a/jetty-websocket/websocket-servlet/pom.xml
+++ b/jetty-websocket/websocket-servlet/pom.xml
@@ -3,7 +3,7 @@
     <parent>
         <groupId>org.eclipse.jetty.websocket</groupId>
         <artifactId>websocket-parent</artifactId>
-        <version>9.0.1-SNAPSHOT</version>
+        <version>9.0.2-SNAPSHOT</version>
     </parent>
 
     <modelVersion>4.0.0</modelVersion>
diff --git a/jetty-xml/pom.xml b/jetty-xml/pom.xml
index 111f47a..d8a39e8 100644
--- a/jetty-xml/pom.xml
+++ b/jetty-xml/pom.xml
@@ -2,7 +2,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jetty-xml</artifactId>
diff --git a/pom.xml b/pom.xml
index 36e9d6e..0ffd760 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
     <version>20</version>
   </parent>
   <artifactId>jetty-project</artifactId>
-  <version>9.0.1-SNAPSHOT</version>
+  <version>9.0.2-SNAPSHOT</version>
   <name>Jetty :: Project</name>
   <url>${jetty.url}</url>
   <packaging>pom</packaging>
@@ -286,7 +286,7 @@
           <groupId>org.apache.maven.plugins</groupId>
           <artifactId>maven-surefire-plugin</artifactId>
           <configuration>
-            <argLine>-showversion -XX:+PrintGCDetails</argLine>
+            <argLine>-showversion -Xmx1g -Xms1g -XX:+PrintGCDetails</argLine>
             <failIfNoTests>false</failIfNoTests>
             <!--systemProperties>
               <property>
@@ -709,7 +709,7 @@
                       })();
                    </script>
                 ]]>
-              </header>           
+              </header>
             </configuration>
           </plugin>
         </plugins>
diff --git a/tests/pom.xml b/tests/pom.xml
index fff3d3a..707898b 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.eclipse.jetty</groupId>
     <artifactId>jetty-project</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
   <groupId>org.eclipse.jetty.tests</groupId>
diff --git a/tests/test-continuation/pom.xml b/tests/test-continuation/pom.xml
index c63dceb..e0da1c4 100644
--- a/tests/test-continuation/pom.xml
+++ b/tests/test-continuation/pom.xml
@@ -20,7 +20,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>tests-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>
diff --git a/tests/test-loginservice/pom.xml b/tests/test-loginservice/pom.xml
index ef098c4..99e5b6d 100644
--- a/tests/test-loginservice/pom.xml
+++ b/tests/test-loginservice/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>tests-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>test-loginservice</artifactId>
   <name>Jetty Tests :: Login Service</name>
diff --git a/tests/test-sessions/pom.xml b/tests/test-sessions/pom.xml
index a9262e0..dac1976 100644
--- a/tests/test-sessions/pom.xml
+++ b/tests/test-sessions/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>tests-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>test-sessions-parent</artifactId>
   <name>Jetty Tests :: Sessions :: Parent</name>
diff --git a/tests/test-sessions/test-hash-sessions/pom.xml b/tests/test-sessions/test-hash-sessions/pom.xml
index 995656f..5a52c04 100644
--- a/tests/test-sessions/test-hash-sessions/pom.xml
+++ b/tests/test-sessions/test-hash-sessions/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-sessions-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>test-hash-sessions</artifactId>
   <name>Jetty Tests :: Sessions :: Hash</name>
diff --git a/tests/test-sessions/test-jdbc-sessions/pom.xml b/tests/test-sessions/test-jdbc-sessions/pom.xml
index 286b537..46e03ba 100644
--- a/tests/test-sessions/test-jdbc-sessions/pom.xml
+++ b/tests/test-sessions/test-jdbc-sessions/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-sessions-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>test-jdbc-sessions</artifactId>
   <name>Jetty Tests :: Sessions :: JDBC</name>
diff --git a/tests/test-sessions/test-sessions-common/pom.xml b/tests/test-sessions/test-sessions-common/pom.xml
index 37ea24b..7c7a8b6 100644
--- a/tests/test-sessions/test-sessions-common/pom.xml
+++ b/tests/test-sessions/test-sessions-common/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-sessions-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>test-sessions-common</artifactId>
   <name>Jetty Tests :: Sessions :: Common</name>
diff --git a/tests/test-webapps/pom.xml b/tests/test-webapps/pom.xml
index e519719..f6ae886 100644
--- a/tests/test-webapps/pom.xml
+++ b/tests/test-webapps/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>tests-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
   <artifactId>test-webapps-parent</artifactId>
diff --git a/tests/test-webapps/test-jaas-webapp/pom.xml b/tests/test-webapps/test-jaas-webapp/pom.xml
index e77d24a..fbffd7d 100644
--- a/tests/test-webapps/test-jaas-webapp/pom.xml
+++ b/tests/test-webapps/test-jaas-webapp/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-webapps-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>test-jaas-webapp</artifactId>
   <name>Jetty Tests :: WebApp :: JAAS</name>
diff --git a/tests/test-webapps/test-jetty-webapp/pom.xml b/tests/test-webapps/test-jetty-webapp/pom.xml
index 8efd3b7..6aae466 100644
--- a/tests/test-webapps/test-jetty-webapp/pom.xml
+++ b/tests/test-webapps/test-jetty-webapp/pom.xml
@@ -20,7 +20,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-webapps-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>
diff --git a/tests/test-webapps/test-jndi-webapp/pom.xml b/tests/test-webapps/test-jndi-webapp/pom.xml
index 0ef65dc..dd1a649 100644
--- a/tests/test-webapps/test-jndi-webapp/pom.xml
+++ b/tests/test-webapps/test-jndi-webapp/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-webapps-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>test-jndi-webapp</artifactId>
   <name>Jetty Tests :: WebApp :: JNDI</name>
diff --git a/tests/test-webapps/test-mock-resources/pom.xml b/tests/test-webapps/test-mock-resources/pom.xml
index edc6c82..8bc98f2 100644
--- a/tests/test-webapps/test-mock-resources/pom.xml
+++ b/tests/test-webapps/test-mock-resources/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-webapps-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <name>Jetty Tests :: WebApp :: Mock Resources</name>
   <artifactId>test-mock-resources</artifactId>
diff --git a/tests/test-webapps/test-proxy-webapp/pom.xml b/tests/test-webapps/test-proxy-webapp/pom.xml
index 5cab4d1..42d5057 100644
--- a/tests/test-webapps/test-proxy-webapp/pom.xml
+++ b/tests/test-webapps/test-proxy-webapp/pom.xml
@@ -20,7 +20,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-webapps-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
     <relativePath>../pom.xml</relativePath>
   </parent>
   <modelVersion>4.0.0</modelVersion>
diff --git a/tests/test-webapps/test-servlet-spec/pom.xml b/tests/test-webapps/test-servlet-spec/pom.xml
index be5640d..6c61e57 100644
--- a/tests/test-webapps/test-servlet-spec/pom.xml
+++ b/tests/test-webapps/test-servlet-spec/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-webapps-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>test-servlet-spec-parent</artifactId>
   <name>Jetty Tests :: Spec Test WebApp :: Parent</name>
diff --git a/tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml b/tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml
index f5ec148..13ea272 100644
--- a/tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml
+++ b/tests/test-webapps/test-servlet-spec/test-container-initializer/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-servlet-spec-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>test-container-initializer</artifactId>
   <packaging>jar</packaging>
diff --git a/tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml b/tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml
index ea70ea8..44ac6d8 100644
--- a/tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml
+++ b/tests/test-webapps/test-servlet-spec/test-spec-webapp/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-servlet-spec-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <name>Jetty Tests :: Webapps :: Spec Webapp</name>
   <artifactId>test-spec-webapp</artifactId>
diff --git a/tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml b/tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml
index f830a12..e04bb17 100644
--- a/tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml
+++ b/tests/test-webapps/test-servlet-spec/test-web-fragment/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-servlet-spec-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <name>Jetty Tests :: WebApp :: Servlet Spec :: Fragment Jar</name>
   <groupId>org.eclipse.jetty.tests</groupId>
diff --git a/tests/test-webapps/test-webapp-rfc2616/pom.xml b/tests/test-webapps/test-webapp-rfc2616/pom.xml
index c8e3b97..0dd389f 100644
--- a/tests/test-webapps/test-webapp-rfc2616/pom.xml
+++ b/tests/test-webapps/test-webapp-rfc2616/pom.xml
@@ -21,7 +21,7 @@
   <parent>
     <groupId>org.eclipse.jetty.tests</groupId>
     <artifactId>test-webapps-parent</artifactId>
-    <version>9.0.1-SNAPSHOT</version>
+    <version>9.0.2-SNAPSHOT</version>
   </parent>
   <artifactId>test-webapp-rfc2616</artifactId>
   <name>Jetty Tests :: WebApp :: RFC2616</name>