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()
- * {
- * @Override
- * public boolean supports()
- * {
- * return true;
- * }
- *
- * @Override
- * public void unsupported()
- * {
- * }
- *
- * @Override
- * public String selectProtocol(List<String> protocols)
- * {
- * return protocols.get(0);
- * }
- * });
- * </pre>
- * <p>Server side typical usage:</p>
- * <pre>
- * SSLSocket sslSocket = ...;
- * NextProtoNego.put(sslSocket, new NextProtoNego.ServerProvider()
- * {
- * @Override
- * public void unsupported()
- * {
- * }
- *
- * @Override
- * public List<String> protocols()
- * {
- * return Arrays.asList("http/1.1");
- * }
- *
- * @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 <New
- * class="org.eclipse.jetty.deploy.providers.WebAppProvider"> .... <Set
- * name="tldBundles"><Property name="org.eclipse.jetty.osgi.tldsbundles"
- * default="" /></Set> <New>
- */
-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>