From 45e474b7d535d3f0bf8a26eca4daea848db797ca Mon Sep 17 00:00:00 2001
From: Ludovic Orban
Date: Thu, 2 May 2024 12:09:29 +0200
Subject: [PATCH 1/5] Improve ThreadLimitHandler (#11723)
* Improve ThreadLimitHandler
Signed-off-by: Ludovic Orban
---
.../server/handler/ThreadLimitHandler.java | 41 ++++++++++++-------
.../handler/ThreadLimitHandlerTest.java | 10 +++++
.../jetty/ee9/nested/ThreadLimitHandler.java | 36 ++++++++++++----
3 files changed, 64 insertions(+), 23 deletions(-)
diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ThreadLimitHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ThreadLimitHandler.java
index 939f55429b0..19cc269220f 100644
--- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ThreadLimitHandler.java
+++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ThreadLimitHandler.java
@@ -21,7 +21,6 @@ import java.util.Deque;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicReference;
import java.util.function.Consumer;
@@ -31,6 +30,7 @@ import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpStatus;
import org.eclipse.jetty.http.QuotedCSV;
+import org.eclipse.jetty.io.Retainable;
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
@@ -68,7 +68,7 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
private final boolean _rfc7239;
private final String _forwardedHeader;
- private final ConcurrentMap _remotes = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap _remotes = new ConcurrentHashMap<>();
private volatile boolean _enabled;
private int _threadLimit = 10;
@@ -163,7 +163,10 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
}
// We accept the request and will always handle it.
- LimitedRequest limitedRequest = new LimitedRequest(remote, next, request, response, callback);
+ // Use a compute method to remove the Remote instance as it is necessary for
+ // the ref counter release and the removal to be atomic.
+ LimitedRequest limitedRequest = new LimitedRequest(remote, next, request, response, Callback.from(callback, () ->
+ _remotes.computeIfPresent(remote._ip, (k, v) -> v._referenceCounter.release() ? null : v)));
limitedRequest.handle();
return true;
}
@@ -177,7 +180,8 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
private Remote getRemote(Request baseRequest)
{
String ip = getRemoteIP(baseRequest);
- LOG.debug("ip={}", ip);
+ if (LOG.isDebugEnabled())
+ LOG.debug("ip={}", ip);
if (ip == null)
return null;
@@ -185,15 +189,18 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
if (limit <= 0)
return null;
- Remote remote = _remotes.get(ip);
- if (remote == null)
+ // Use a compute method to create or retain the Remote instance as it is necessary for
+ // the ref counter increment or the instance creation to be mutually exclusive.
+ // The map MUST be a CHM as it guarantees the remapping function is only called once.
+ return _remotes.compute(ip, (k, v) ->
{
- Remote r = new Remote(baseRequest.getContext(), ip, limit);
- remote = _remotes.putIfAbsent(ip, r);
- if (remote == null)
- remote = r;
- }
- return remote;
+ if (v != null)
+ {
+ v._referenceCounter.retain();
+ return v;
+ }
+ return new Remote(baseRequest.getContext(), k, limit);
+ });
}
protected String getRemoteIP(Request baseRequest)
@@ -208,7 +215,7 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
}
// If no remote IP from a header, determine it directly from the channel
- // Do not use the request methods, as they may have been lied to by the
+ // Do not use the request methods, as they may have been lied to by the
// RequestCustomizer!
if (baseRequest.getConnectionMetaData().getRemoteSocketAddress() instanceof InetSocketAddress inetAddr)
{
@@ -255,7 +262,12 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
int comma = forwardedFor.lastIndexOf(',');
return (comma >= 0) ? forwardedFor.substring(comma + 1).trim() : forwardedFor;
}
-
+
+ int getRemoteCount()
+ {
+ return _remotes.size();
+ }
+
private static class LimitedRequest extends Request.Wrapper
{
private final Remote _remote;
@@ -517,6 +529,7 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
private static final class Remote
{
private final Executor _executor;
+ private final Retainable.ReferenceCounter _referenceCounter = new Retainable.ReferenceCounter();
private final String _ip;
private final int _limit;
private final AutoLock _lock = new AutoLock();
diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ThreadLimitHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ThreadLimitHandlerTest.java
index 87e7dfbdaed..dd7d5815236 100644
--- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ThreadLimitHandlerTest.java
+++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ThreadLimitHandlerTest.java
@@ -104,6 +104,8 @@ public class ThreadLimitHandlerTest
last.set(null);
_local.getResponse("GET / HTTP/1.0\r\nForwarded: for=1.2.3.4\r\n\r\n");
assertThat(last.get(), is("0.0.0.0"));
+
+ await().atMost(5, TimeUnit.SECONDS).until(handler::getRemoteCount, is(0));
}
@Test
@@ -147,6 +149,8 @@ public class ThreadLimitHandlerTest
last.set(null);
_local.getResponse("GET / HTTP/1.0\r\nX-Forwarded-For: 1.1.1.1\r\nX-Forwarded-For: 6.6.6.6,1.2.3.4\r\nForwarded: for=1.2.3.4\r\n\r\n");
assertThat(last.get(), is("1.2.3.4"));
+
+ await().atMost(5, TimeUnit.SECONDS).until(handler::getRemoteCount, is(0));
}
@Test
@@ -190,6 +194,8 @@ public class ThreadLimitHandlerTest
last.set(null);
_local.getResponse("GET / HTTP/1.0\r\nX-Forwarded-For: 1.1.1.1\r\nForwarded: for=6.6.6.6; for=1.2.3.4\r\nX-Forwarded-For: 6.6.6.6\r\nForwarded: proto=https\r\n\r\n");
assertThat(last.get(), is("1.2.3.4"));
+
+ await().atMost(5, TimeUnit.SECONDS).until(handler::getRemoteCount, is(0));
}
@Test
@@ -248,6 +254,8 @@ public class ThreadLimitHandlerTest
await().atMost(10, TimeUnit.SECONDS).until(total::get, is(10));
await().atMost(10, TimeUnit.SECONDS).until(count::get, is(0));
+
+ await().atMost(5, TimeUnit.SECONDS).until(handler::getRemoteCount, is(0));
}
@Test
@@ -367,5 +375,7 @@ public class ThreadLimitHandlerTest
assertThat(response, containsString(" 200 OK"));
assertThat(response, containsString(" read 2"));
}
+
+ await().atMost(5, TimeUnit.SECONDS).until(handler::getRemoteCount, is(0));
}
}
diff --git a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ThreadLimitHandler.java b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ThreadLimitHandler.java
index 06356c21cde..1748c1053c2 100644
--- a/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ThreadLimitHandler.java
+++ b/jetty-ee9/jetty-ee9-nested/src/main/java/org/eclipse/jetty/ee9/nested/ThreadLimitHandler.java
@@ -21,17 +21,19 @@ import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import jakarta.servlet.AsyncContext;
import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequestEvent;
+import jakarta.servlet.ServletRequestListener;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HostPortHttpField;
import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.QuotedCSV;
+import org.eclipse.jetty.io.Retainable;
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
import org.eclipse.jetty.util.IncludeExcludeSet;
import org.eclipse.jetty.util.InetAddressSet;
@@ -72,7 +74,7 @@ public class ThreadLimitHandler extends HandlerWrapper
private final boolean _rfc7239;
private final String _forwardedHeader;
private final IncludeExcludeSet _includeExcludeSet = new IncludeExcludeSet<>(InetAddressSet.class);
- private final ConcurrentMap _remotes = new ConcurrentHashMap<>();
+ private final ConcurrentHashMap _remotes = new ConcurrentHashMap<>();
private volatile boolean _enabled;
private int _threadLimit = 10;
@@ -178,6 +180,17 @@ public class ThreadLimitHandler extends HandlerWrapper
}
else
{
+ baseRequest.addEventListener(new ServletRequestListener()
+ {
+ @Override
+ public void requestDestroyed(ServletRequestEvent sre)
+ {
+ // Use a compute method to remove the Remote instance as it is necessary for
+ // the ref counter release and the removal to be atomic.
+ _remotes.computeIfPresent(remote._ip, (k, v) -> v._referenceCounter.release() ? null : v);
+ }
+ });
+
// Do we already have a future permit from a previous invocation?
Closeable permit = (Closeable)baseRequest.getAttribute(PERMIT);
try
@@ -249,14 +262,18 @@ public class ThreadLimitHandler extends HandlerWrapper
if (limit <= 0)
return null;
- remote = _remotes.get(ip);
- if (remote == null)
+ // Use a compute method to create or retain the Remote instance as it is necessary for
+ // the ref counter increment or the instance creation to be mutually exclusive.
+ // The map MUST be a CHM as it guarantees the remapping function is only called once.
+ remote = _remotes.compute(ip, (k, v) ->
{
- Remote r = new Remote(ip, limit);
- remote = _remotes.putIfAbsent(ip, r);
- if (remote == null)
- remote = r;
- }
+ if (v != null)
+ {
+ v._referenceCounter.retain();
+ return v;
+ }
+ return new Remote(k, limit);
+ });
baseRequest.setAttribute(REMOTE, remote);
@@ -325,6 +342,7 @@ public class ThreadLimitHandler extends HandlerWrapper
private final String _ip;
private final int _limit;
private final AutoLock _lock = new AutoLock();
+ private final Retainable.ReferenceCounter _referenceCounter = new Retainable.ReferenceCounter();
private int _permits;
private Deque> _queue = new ArrayDeque<>();
private final CompletableFuture _permitted = CompletableFuture.completedFuture(this);
From cfee4fe433103f759478f0ce99ed98689ffd83d4 Mon Sep 17 00:00:00 2001
From: Ludovic Orban
Date: Thu, 2 May 2024 12:10:37 +0200
Subject: [PATCH 2/5] Fix flaky
`testUploadWithPendingReadConcurrentServerCloseClosesStream()` (#11693)
* #11692 fix flaky testUploadWithPendingReadConcurrentServerCloseClosesStream()
Signed-off-by: Ludovic Orban
---
.../jetty-test-client-transports/pom.xml | 16 ++++++++++++++++
.../client/transport/HttpClientStreamTest.java | 13 +++----------
2 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/jetty-core/jetty-tests/jetty-test-client-transports/pom.xml b/jetty-core/jetty-tests/jetty-test-client-transports/pom.xml
index 7c34aa4131b..348585e02b1 100644
--- a/jetty-core/jetty-tests/jetty-test-client-transports/pom.xml
+++ b/jetty-core/jetty-tests/jetty-test-client-transports/pom.xml
@@ -86,6 +86,22 @@
+
+ enable-foreign
+
+ [22,)
+
+
+
+
+ maven-surefire-plugin
+
+ @{argLine} ${jetty.surefire.argLine} --enable-native-access=ALL-UNNAMED
+
+
+
+
+
diff --git a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientStreamTest.java b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientStreamTest.java
index 703bc69c6f2..216b24cc119 100644
--- a/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientStreamTest.java
+++ b/jetty-core/jetty-tests/jetty-test-client-transports/src/test/java/org/eclipse/jetty/test/client/transport/HttpClientStreamTest.java
@@ -1063,9 +1063,7 @@ public class HttpClientStreamTest extends AbstractTest
@MethodSource("transports")
public void testUploadWithPendingReadConcurrentServerCloseClosesStream(Transport transport) throws Exception
{
- CountDownLatch serverDemandLatch = new CountDownLatch(1);
CountDownLatch serverLatch = new CountDownLatch(1);
- AtomicReference lastChunk = new AtomicReference<>();
start(transport, new Handler.Abstract()
{
@Override
@@ -1076,16 +1074,14 @@ public class HttpClientStreamTest extends AbstractTest
@Override
public void run()
{
+ // With H2, once the connector is stopping, there is no guarantee that the demand will be serviced
+ // as the execution strategy is busy shutting down but is needed to run the dispatched thread that
+ // services the demand; so we cannot expect that a last chunk will be read here.
Content.Chunk chunk = request.read();
if (chunk != null)
chunk.release();
if (chunk == null || !chunk.isLast())
- {
request.demand(this);
- return;
- }
- lastChunk.set(chunk);
- serverDemandLatch.countDown();
}
});
serverLatch.countDown();
@@ -1149,9 +1145,6 @@ public class HttpClientStreamTest extends AbstractTest
assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
assertTrue(closeLatch.await(5, TimeUnit.SECONDS));
- assertTrue(serverDemandLatch.await(5, TimeUnit.SECONDS));
- assertTrue(Content.Chunk.isFailure(lastChunk.get(), true));
- assertInstanceOf(IOException.class, lastChunk.get().getFailure());
}
@ParameterizedTest
From 42ba41531897178348c4cf0328c4609adfd8874d Mon Sep 17 00:00:00 2001
From: Simone Bordet
Date: Thu, 2 May 2024 17:40:49 +0200
Subject: [PATCH 3/5] Addendum to #11566. (#11722)
* Addendum to #11566.
Restored methods that were removed in WebAppClassLoader.Context.
Fixed method signatures for deprecated method -- they must take the deprecated ClassMatcher, not the newly introduced one.
Signed-off-by: Simone Bordet
---
.../eclipse/jetty/ee/WebAppClassLoading.java | 3 +-
.../jetty/util/ClassVisibilityChecker.java | 12 ++--
.../jetty/ee10/cdi/CdiConfiguration.java | 8 +--
.../ee10/webapp/AbstractConfiguration.java | 28 ++++----
.../jetty/ee10/webapp/ClassMatcher.java | 1 -
.../jetty/ee10/webapp/Configuration.java | 31 +++++++--
.../jetty/ee10/webapp/WebAppClassLoader.java | 33 +++++++--
.../jetty/ee10/webapp/WebAppContext.java | 68 +++++++------------
.../ee10/webapp/WebAppClassLoaderTest.java | 3 +-
.../jetty/ee9/webapp/ClassMatcher.java | 5 --
.../jetty/ee9/webapp/Configuration.java | 2 +-
.../jetty/ee9/webapp/WebAppClassLoader.java | 5 --
.../jetty/ee9/webapp/WebAppContext.java | 19 ++++--
.../ee9/webapp/WebAppClassLoaderTest.java | 4 +-
14 files changed, 119 insertions(+), 103 deletions(-)
diff --git a/jetty-core/jetty-ee/src/main/java/org/eclipse/jetty/ee/WebAppClassLoading.java b/jetty-core/jetty-ee/src/main/java/org/eclipse/jetty/ee/WebAppClassLoading.java
index eaf13e52a64..dcdac85af03 100644
--- a/jetty-core/jetty-ee/src/main/java/org/eclipse/jetty/ee/WebAppClassLoading.java
+++ b/jetty-core/jetty-ee/src/main/java/org/eclipse/jetty/ee/WebAppClassLoading.java
@@ -169,8 +169,9 @@ public class WebAppClassLoading
* Add a hidden (server) Class pattern to use for all WebAppContexts of a given {@link Server}.
* @param attributes The {@link Attributes} instance to add classes to
* @param patterns the patterns to use
+ * @deprecated use {@link #addHiddenClasses(Server, String...)} instead
*/
- @Deprecated (forRemoval = true)
+ @Deprecated (since = "12.0.9", forRemoval = true)
public static void addHiddenClasses(Attributes attributes, String... patterns)
{
if (patterns != null && patterns.length > 0)
diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/ClassVisibilityChecker.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/ClassVisibilityChecker.java
index 12bfaec2322..e9d273a7e5e 100644
--- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/ClassVisibilityChecker.java
+++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/ClassVisibilityChecker.java
@@ -21,7 +21,7 @@ public interface ClassVisibilityChecker
{
/**
* Is the class a Protected (System) Class.
- * A System class is a class that is visible to a webapplication,
+ * A System class is a class that is visible to a web application,
* but that cannot be overridden by the contents of WEB-INF/lib or
* WEB-INF/classes
*
@@ -33,8 +33,8 @@ public interface ClassVisibilityChecker
/**
* Is the class a Hidden (Server) Class.
* A Server class is a class that is part of the implementation of
- * the server and is NIT visible to a webapplication. The web
- * application may provide it's own implementation of the class,
+ * the server and is NOT visible to a web application. The web
+ * application may provide its own implementation of the class,
* to be loaded from WEB-INF/lib or WEB-INF/classes
*
* @param clazz The fully qualified name of the class.
@@ -44,7 +44,7 @@ public interface ClassVisibilityChecker
/**
* Is the class a System Class.
- * A System class is a class that is visible to a webapplication,
+ * A System class is a class that is visible to a web application,
* but that cannot be overridden by the contents of WEB-INF/lib or
* WEB-INF/classes
*
@@ -61,8 +61,8 @@ public interface ClassVisibilityChecker
/**
* Is the class a Server Class.
* A Server class is a class that is part of the implementation of
- * the server and is NIT visible to a webapplication. The web
- * application may provide it's own implementation of the class,
+ * the server and is NOT visible to a web application. The web
+ * application may provide its own implementation of the class,
* to be loaded from WEB-INF/lib or WEB-INF/classes
*
* @param clazz The fully qualified name of the class.
diff --git a/jetty-ee10/jetty-ee10-cdi/src/main/java/org/eclipse/jetty/ee10/cdi/CdiConfiguration.java b/jetty-ee10/jetty-ee10-cdi/src/main/java/org/eclipse/jetty/ee10/cdi/CdiConfiguration.java
index 07370998d8d..32ed6ef47c4 100644
--- a/jetty-ee10/jetty-ee10-cdi/src/main/java/org/eclipse/jetty/ee10/cdi/CdiConfiguration.java
+++ b/jetty-ee10/jetty-ee10-cdi/src/main/java/org/eclipse/jetty/ee10/cdi/CdiConfiguration.java
@@ -13,8 +13,6 @@
package org.eclipse.jetty.ee10.cdi;
-import java.util.function.Predicate;
-
import org.eclipse.jetty.ee10.annotations.AnnotationConfiguration;
import org.eclipse.jetty.ee10.plus.webapp.PlusConfiguration;
import org.eclipse.jetty.ee10.webapp.AbstractConfiguration;
@@ -33,11 +31,11 @@ public class CdiConfiguration extends AbstractConfiguration
{
super(new Builder()
.protectAndExpose("org.eclipse.jetty.ee10.cdi.CdiServletContainerInitializer")
- .hide(getHiddenClasses())
+ .hide(getCdiHiddenClasses())
.addDependents(AnnotationConfiguration.class, PlusConfiguration.class));
}
- private static String[] getHiddenClasses()
+ private static String[] getCdiHiddenClasses()
{
//Only hide the cdi api classes if there is not also an impl on the
//environment classpath - vital for embedded uses.
@@ -45,4 +43,4 @@ public class CdiConfiguration extends AbstractConfiguration
return new String[]{"jakarta.enterprise.", "jakarta.decorator."};
return new String[0];
}
-}
\ No newline at end of file
+}
diff --git a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/AbstractConfiguration.java b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/AbstractConfiguration.java
index 2db4056c8bd..ae04963208c 100644
--- a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/AbstractConfiguration.java
+++ b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/AbstractConfiguration.java
@@ -19,13 +19,15 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import org.eclipse.jetty.util.ClassMatcher;
+
public class AbstractConfiguration implements Configuration
{
private final boolean _enabledByDefault;
private final List _after;
private final List _before;
- private final ClassMatcher _system;
- private final ClassMatcher _server;
+ private final ClassMatcher _protected;
+ private final ClassMatcher _hidden;
public static class Builder
{
@@ -88,7 +90,7 @@ public class AbstractConfiguration implements Configuration
/**
* Protect classes from modification by the web application by adding them
- * to the {@link WebAppConfiguration#getSystemClasses()}
+ * to the {@link WebAppConfiguration#getProtectedClasses()}
*
* @param classes classname or package pattern
*/
@@ -100,7 +102,7 @@ public class AbstractConfiguration implements Configuration
/**
* Hide classes from the web application by adding them
- * to the {@link WebAppConfiguration#getServerClasses()}
+ * to the {@link WebAppConfiguration#getHiddenClasses()}
*
* @param classes classname or package pattern
*/
@@ -112,7 +114,7 @@ public class AbstractConfiguration implements Configuration
/**
* Expose classes to the web application by adding them
- * as exclusions to the {@link WebAppConfiguration#getServerClasses()}
+ * as exclusions to the {@link WebAppConfiguration#getHiddenClasses()}
*
* @param classes classname or package pattern
*/
@@ -129,9 +131,9 @@ public class AbstractConfiguration implements Configuration
/**
* Protect classes from modification by the web application by adding them
- * to the {@link WebAppConfiguration#getSystemClasses()} and
+ * to the {@link WebAppConfiguration#getProtectedClasses()} and
* expose them to the web application by adding them
- * as exclusions to the {@link WebAppConfiguration#getServerClasses()}
+ * as exclusions to the {@link WebAppConfiguration#getHiddenClasses()}
*
* @param classes classname or package pattern
*/
@@ -154,8 +156,8 @@ public class AbstractConfiguration implements Configuration
_enabledByDefault = builder._enabledByDefault;
_after = List.copyOf(builder._after);
_before = List.copyOf(builder._before);
- _system = new ClassMatcher(builder._system).asImmutable();
- _server = new ClassMatcher(builder._server).asImmutable();
+ _protected = new ClassMatcher(builder._system).asImmutable();
+ _hidden = new ClassMatcher(builder._server).asImmutable();
}
@Override
@@ -171,15 +173,15 @@ public class AbstractConfiguration implements Configuration
}
@Override
- public ClassMatcher getSystemClasses()
+ public ClassMatcher getProtectedClasses()
{
- return _system;
+ return _protected;
}
@Override
- public ClassMatcher getServerClasses()
+ public ClassMatcher getHiddenClasses()
{
- return _server;
+ return _hidden;
}
@Override
diff --git a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/ClassMatcher.java b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/ClassMatcher.java
index 23a625dcd1c..3eb611146b6 100644
--- a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/ClassMatcher.java
+++ b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/ClassMatcher.java
@@ -21,7 +21,6 @@ import org.eclipse.jetty.util.IncludeExcludeSet;
/**
* @deprecated Use org.eclipse.jetty.util.ClassMatcher
*/
-
@Deprecated(since = "12.0.8", forRemoval = true)
public class ClassMatcher extends org.eclipse.jetty.util.ClassMatcher
{
diff --git a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/Configuration.java b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/Configuration.java
index ca8e4934ecd..1f172c43fe3 100644
--- a/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/Configuration.java
+++ b/jetty-ee10/jetty-ee10-webapp/src/main/java/org/eclipse/jetty/ee10/webapp/Configuration.java
@@ -17,6 +17,7 @@ import java.util.Collection;
import java.util.Collections;
import java.util.ServiceLoader;
+import org.eclipse.jetty.util.ClassMatcher;
import org.eclipse.jetty.util.TopologicalSort;
/**
@@ -43,8 +44,8 @@ import org.eclipse.jetty.util.TopologicalSort;
* (eg {@link JndiConfiguration}, {@link JaasConfiguration}} etc.) can be added or removed without concern
* for ordering.
*
- *
Also since Jetty-9.4, Configurations are responsible for providing {@link #getServerClasses()} and
- * {@link #getSystemClasses()} to configure the {@link WebAppClassLoader} for each context.
+ *
Also since Jetty-9.4, Configurations are responsible for providing {@link #getHiddenClasses()} and
+ * {@link #getProtectedClasses()} to configure the {@link WebAppClassLoader} for each context.
*
*/
public interface Configuration
@@ -93,25 +94,43 @@ public interface Configuration
}
/**
- * Get the system classes associated with this Configuration.
+ * Get the system (protected) classes associated with this Configuration.
*
* @return ClassMatcher of system classes.
*/
- default ClassMatcher getSystemClasses()
+ default ClassMatcher getProtectedClasses()
{
return new ClassMatcher();
}
/**
- * Get the system classes associated with this Configuration.
+ * Get the server (hidden) classes associated with this Configuration.
*
* @return ClassMatcher of server classes.
*/
- default ClassMatcher getServerClasses()
+ default ClassMatcher getHiddenClasses()
{
return new ClassMatcher();
}
+ /**
+ * @deprecated use {@link #getProtectedClasses()} instead
+ */
+ @Deprecated(since = "12.0.8", forRemoval = true)
+ default org.eclipse.jetty.ee10.webapp.ClassMatcher getSystemClasses()
+ {
+ return new org.eclipse.jetty.ee10.webapp.ClassMatcher(getProtectedClasses());
+ }
+
+ /**
+ * @deprecated use {@link #getHiddenClasses()} instead
+ */
+ @Deprecated(since = "12.0.8", forRemoval = true)
+ default org.eclipse.jetty.ee10.webapp.ClassMatcher getServerClasses()
+ {
+ return new org.eclipse.jetty.ee10.webapp.ClassMatcher(getHiddenClasses());
+ }
+
/**
* Set up for configuration.
*
- * These classes/packages are used to implement the server and are hiddenClasses
+ * These classes/packages are used to implement the server and are hidden
* from the context. If the context needs to load these classes, it must have its
* own copy of them in WEB-INF/lib or WEB-INF/classes.
*
@@ -635,7 +635,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
}
/**
- * Set the protected (aka system) classes patterns.
+ * Set the protected (system) classes patterns.
*
* These classes/packages are provided by the JVM and
* cannot be replaced by classes of the same name from WEB-INF,
@@ -680,7 +680,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
}
/**
- * @return The ClassMatcher used to match Server (hiddenClasses) classes
+ * @return The ClassMatcher used to match Server (hidden) classes
*/
public ClassMatcher getHiddenClassMatcher()
{
@@ -693,7 +693,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
return _protectedClasses.getPatterns();
}
- @ManagedAttribute(value = "classes and packages hiddenClasses by the context classloader", readonly = true)
+ @ManagedAttribute(value = "classes and packages hidden by the context classloader", readonly = true)
public String[] getHiddenClasses()
{
return _hiddenClasses.getPatterns();
@@ -727,56 +727,54 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
* @deprecated use {@link #setHiddenClassMatcher(ClassMatcher)}
*/
@Deprecated(since = "12.0.8", forRemoval = true)
- public void setServerClassMatcher(ClassMatcher serverClasses)
+ public void setServerClassMatcher(org.eclipse.jetty.ee10.webapp.ClassMatcher serverClasses)
{
- _hiddenClasses.clear();
- _hiddenClasses.add(serverClasses.getPatterns());
+ setHiddenClassMatcher(serverClasses);
}
/**
* @deprecated use {@link #setProtectedClassMatcher(ClassMatcher)}
*/
@Deprecated(since = "12.0.8", forRemoval = true)
- public void setSystemClassMatcher(ClassMatcher systemClasses)
+ public void setSystemClassMatcher(org.eclipse.jetty.ee10.webapp.ClassMatcher systemClasses)
{
- _protectedClasses.clear();
- _protectedClasses.add(systemClasses.getPatterns());
+ setProtectedClassMatcher(systemClasses);
}
/**
* @deprecated use {@link #addHiddenClassMatcher(ClassMatcher)}
*/
@Deprecated(since = "12.0.8", forRemoval = true)
- public void addServerClassMatcher(ClassMatcher serverClasses)
+ public void addServerClassMatcher(org.eclipse.jetty.ee10.webapp.ClassMatcher serverClasses)
{
- _hiddenClasses.add(serverClasses.getPatterns());
+ addHiddenClassMatcher(serverClasses);
}
/**
* @deprecated use {@link #addProtectedClassMatcher(ClassMatcher)}
*/
@Deprecated(since = "12.0.8", forRemoval = true)
- public void addSystemClassMatcher(ClassMatcher systemClasses)
+ public void addSystemClassMatcher(org.eclipse.jetty.ee10.webapp.ClassMatcher systemClasses)
{
- _protectedClasses.add(systemClasses.getPatterns());
+ addProtectedClassMatcher(systemClasses);
}
/**
* @deprecated use {@link #getProtectedClassMatcher()}
*/
@Deprecated(since = "12.0.8", forRemoval = true)
- public ClassMatcher getSystemClassMatcher()
+ public org.eclipse.jetty.ee10.webapp.ClassMatcher getSystemClassMatcher()
{
- return _protectedClasses;
+ return new org.eclipse.jetty.ee10.webapp.ClassMatcher(getProtectedClassMatcher());
}
/**
* @deprecated use {@link #getHiddenClassMatcher()}
*/
@Deprecated(since = "12.0.8", forRemoval = true)
- public ClassMatcher getServerClassMatcher()
+ public org.eclipse.jetty.ee10.webapp.ClassMatcher getServerClassMatcher()
{
- return _hiddenClasses;
+ return new org.eclipse.jetty.ee10.webapp.ClassMatcher(getHiddenClassMatcher());
}
/**
@@ -785,7 +783,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
@Deprecated(since = "12.0.8", forRemoval = true)
public String[] getSystemClasses()
{
- return _protectedClasses.getPatterns();
+ return getProtectedClasses();
}
/**
@@ -794,7 +792,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
@Deprecated(since = "12.0.8", forRemoval = true)
public String[] getServerClasses()
{
- return _hiddenClasses.getPatterns();
+ return getHiddenClasses();
}
/**
@@ -803,7 +801,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
@Deprecated(since = "12.0.8", forRemoval = true)
public boolean isServerClass(Class> clazz)
{
- return _hiddenClasses.match(clazz);
+ return isHiddenClass(clazz);
}
/**
@@ -812,25 +810,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
@Deprecated(since = "12.0.8", forRemoval = true)
public boolean isSystemClass(Class> clazz)
{
- return _protectedClasses.match(clazz);
- }
-
- /**
- * @deprecated use {@link #isHiddenResource(String, URL)}
- */
- @Deprecated(since = "12.0.8", forRemoval = true)
- public boolean isServerResource(String name, URL url)
- {
- return _hiddenClasses.match(name, url);
- }
-
- /**
- * @deprecated use {@link #isProtectedResource(String, URL)}
- */
- @Deprecated(since = "12.0.8", forRemoval = true)
- public boolean isSystemResource(String name, URL url)
- {
- return _protectedClasses.match(name, url);
+ return isProtectedClass(clazz);
}
@Override
diff --git a/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/WebAppClassLoaderTest.java b/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/WebAppClassLoaderTest.java
index c08c71724ea..b3a55912f23 100644
--- a/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/WebAppClassLoaderTest.java
+++ b/jetty-ee10/jetty-ee10-webapp/src/test/java/org/eclipse/jetty/ee10/webapp/WebAppClassLoaderTest.java
@@ -75,7 +75,7 @@ public class WebAppClassLoaderTest
}
@AfterEach
- public void afterEach() throws Exception
+ public void afterEach()
{
IO.close(_loader);
LifeCycle.stop(_server);
@@ -315,7 +315,6 @@ public class WebAppClassLoaderTest
resources = Collections.list(_loader.getResources("org/acme/resource.txt"));
- expected.clear();
expected.add(webappWebInfLibAcme);
expected.add(webappWebInfClasses);
expected.add(targetTestClasses);
diff --git a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/ClassMatcher.java b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/ClassMatcher.java
index d382b4cf4ac..58ac7a04cad 100644
--- a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/ClassMatcher.java
+++ b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/ClassMatcher.java
@@ -18,11 +18,6 @@ import java.util.Map;
import org.eclipse.jetty.util.IncludeExcludeSet;
-/**
- * @deprecated Use org.eclipse.jetty.util.ClassMatcher
- */
-
-@Deprecated(since = "12.0.8", forRemoval = true)
public class ClassMatcher extends org.eclipse.jetty.util.ClassMatcher
{
public ClassMatcher()
diff --git a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/Configuration.java b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/Configuration.java
index bc0b23f3a68..39fa82a0c5c 100644
--- a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/Configuration.java
+++ b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/Configuration.java
@@ -104,7 +104,7 @@ public interface Configuration
}
/**
- * Get the system classes associated with this Configuration.
+ * Get the server classes associated with this Configuration.
*
* @return ClassMatcher of server classes.
*/
diff --git a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoader.java b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoader.java
index f474fa96ced..01e80965728 100644
--- a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoader.java
+++ b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoader.java
@@ -20,28 +20,24 @@ import java.lang.instrument.IllegalClassFormatException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
-import java.nio.file.Files;
import java.nio.file.Path;
import java.security.CodeSource;
import java.security.PermissionCollection;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Collections;
-import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.CopyOnWriteArrayList;
-import java.util.stream.Stream;
import org.eclipse.jetty.util.ClassVisibilityChecker;
import org.eclipse.jetty.util.FileID;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
import org.eclipse.jetty.util.TypeUtil;
-import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.util.resource.ResourceCollators;
import org.eclipse.jetty.util.resource.ResourceFactory;
@@ -530,7 +526,6 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility
if (webappUrl != null && (!checkSystemResource || !_context.isSystemResource(name, webappUrl)))
{
-
webappClass = this.foundClass(name, webappUrl);
resolveClass(webappClass);
if (LOG.isDebugEnabled())
diff --git a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java
index 574cd0969a6..6e63474b41b 100644
--- a/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java
+++ b/jetty-ee9/jetty-ee9-webapp/src/main/java/org/eclipse/jetty/ee9/webapp/WebAppContext.java
@@ -55,7 +55,6 @@ import org.eclipse.jetty.server.Deployable;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.Attributes;
-import org.eclipse.jetty.util.ClassMatcher;
import org.eclipse.jetty.util.ExceptionUtil;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.StringUtil;
@@ -673,7 +672,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
/**
* Set the server classes patterns.
*
- * Server classes/packages are classes used to implement the server and are hidden
+ * These classes/packages are used to implement the server and are hidden
* from the context. If the context needs to load these classes, it must have its
* own copy of them in WEB-INF/lib or WEB-INF/classes.
*
@@ -688,7 +687,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
/**
* Set the system classes patterns.
*
- * System classes/packages are classes provided by the JVM and that
+ * These classes/packages are provided by the JVM and
* cannot be replaced by classes of the same name from WEB-INF,
* regardless of the value of {@link #setParentLoaderPriority(boolean)}.
*
@@ -753,11 +752,23 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
@Override
public boolean isHiddenClass(Class> clazz)
{
- return _serverClasses.match(clazz);
+ return isServerClass(clazz);
}
@Override
public boolean isProtectedClass(Class> clazz)
+ {
+ return isSystemClass(clazz);
+ }
+
+ @Override
+ public boolean isServerClass(Class> clazz)
+ {
+ return _serverClasses.match(clazz);
+ }
+
+ @Override
+ public boolean isSystemClass(Class> clazz)
{
return _systemClasses.match(clazz);
}
diff --git a/jetty-ee9/jetty-ee9-webapp/src/test/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoaderTest.java b/jetty-ee9/jetty-ee9-webapp/src/test/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoaderTest.java
index af4e50031f4..6ab704340a1 100644
--- a/jetty-ee9/jetty-ee9-webapp/src/test/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoaderTest.java
+++ b/jetty-ee9/jetty-ee9-webapp/src/test/java/org/eclipse/jetty/ee9/webapp/WebAppClassLoaderTest.java
@@ -26,7 +26,6 @@ import java.util.List;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
-import org.eclipse.jetty.util.ClassMatcher;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.resource.Resource;
@@ -75,7 +74,7 @@ public class WebAppClassLoaderTest
}
@AfterEach
- public void afterEach() throws Exception
+ public void afterEach()
{
IO.close(_loader);
LifeCycle.stop(_server);
@@ -315,7 +314,6 @@ public class WebAppClassLoaderTest
resources = Collections.list(_loader.getResources("org/acme/resource.txt"));
- expected.clear();
expected.add(webappWebInfLibAcme);
expected.add(webappWebInfClasses);
expected.add(targetTestClasses);
From c5b2533fdecce21b54c6fbaf36f79bc3ba909775 Mon Sep 17 00:00:00 2001
From: Simone Bordet
Date: Thu, 2 May 2024 18:14:50 +0200
Subject: [PATCH 4/5] Fixed XML files after #11722.
Signed-off-by: Simone Bordet
---
.../jetty-cdi-start-forked/src/main/jetty/jetty-context.xml | 4 ++--
.../jetty-cdi-start-forked/src/main/jetty/jetty-context.xml | 4 ++--
.../jetty-cdi-start-forked/src/main/jetty/jetty-context.xml | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/jetty-ee10/jetty-ee10-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml b/jetty-ee10/jetty-ee10-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml
index 9214a93f9c3..23114b52df7 100644
--- a/jetty-ee10/jetty-ee10-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml
+++ b/jetty-ee10/jetty-ee10-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml
@@ -1,10 +1,10 @@
-
+
-
+
diff --git a/jetty-ee8/jetty-ee8-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml b/jetty-ee8/jetty-ee8-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml
index f7b99769fd8..7ad7d9f0c45 100644
--- a/jetty-ee8/jetty-ee8-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml
+++ b/jetty-ee8/jetty-ee8-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml
@@ -1,12 +1,12 @@
-
+
-
+ -org.eclipse.jetty.util.Decorator
diff --git a/jetty-ee9/jetty-ee9-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml b/jetty-ee9/jetty-ee9-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml
index cfc55f41dfb..8914981f8b4 100644
--- a/jetty-ee9/jetty-ee9-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml
+++ b/jetty-ee9/jetty-ee9-maven-plugin/src/it/jetty-cdi-start-forked/src/main/jetty/jetty-context.xml
@@ -1,12 +1,12 @@
-
+
-
+ -org.eclipse.jetty.util.Decorator
From b11d1cb27fc197d6a7597afd6120cf456389b3be Mon Sep 17 00:00:00 2001
From: Jan Bartel
Date: Fri, 3 May 2024 04:14:46 +0200
Subject: [PATCH 5/5] Issue #11709 fix jetty-with-custom-class.xml file and use
it (#11716)
* Issue #11709 fix jetty-with-custom-class.xml file and use it
---
.../jetty/osgi/JettyServerFactory.java | 8 +-
.../test-jetty-ee10-osgi/pom.xml | 18 +--
.../config/etc/jetty-with-custom-class.xml | 5 +-
.../test/TestJettyOSGiBootWithBundle.java | 123 ++++++++++++++++++
.../jetty/ee10/osgi/test/TestOSGiUtil.java | 33 +----
.../config/etc/jetty-with-custom-class.xml | 2 +-
6 files changed, 143 insertions(+), 46 deletions(-)
create mode 100644 jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/java/org/eclipse/jetty/ee10/osgi/test/TestJettyOSGiBootWithBundle.java
diff --git a/jetty-core/jetty-osgi/src/main/java/org/eclipse/jetty/osgi/JettyServerFactory.java b/jetty-core/jetty-osgi/src/main/java/org/eclipse/jetty/osgi/JettyServerFactory.java
index b7e92e8071a..6cdc433574f 100644
--- a/jetty-core/jetty-osgi/src/main/java/org/eclipse/jetty/osgi/JettyServerFactory.java
+++ b/jetty-core/jetty-osgi/src/main/java/org/eclipse/jetty/osgi/JettyServerFactory.java
@@ -22,6 +22,7 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Optional;
import java.util.StringTokenizer;
import org.eclipse.jetty.deploy.AppLifeCycle;
@@ -195,13 +196,14 @@ public class JettyServerFactory
private static DeploymentManager ensureDeploymentManager(Server server)
{
Collection deployers = server.getBeans(DeploymentManager.class);
- DeploymentManager deploymentManager;
+ DeploymentManager deploymentManager = null;
if (deployers != null)
{
- deploymentManager = deployers.stream().findFirst().get();
+ deploymentManager = deployers.stream().findFirst().orElse(null);
}
- else
+
+ if (deploymentManager == null)
{
deploymentManager = new DeploymentManager();
deploymentManager.setContexts(getContextHandlerCollection(server));
diff --git a/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/pom.xml b/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/pom.xml
index 668e56d8f01..f33daed2bc0 100644
--- a/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/pom.xml
+++ b/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/pom.xml
@@ -42,6 +42,10 @@
+
+ org.eclipse.jetty
+ jetty-slf4j-impl
+ org.eclipse.jetty.ee10.demosjetty-ee10-demo-mock-resources
@@ -263,18 +267,6 @@
jetty-alpn-servertest
-
-
- org.eclipse.jetty
- jetty-slf4j-impl
- test
- org.eclipse.jetty.ee10.demosjetty-ee10-demo-container-initializer
@@ -539,6 +531,8 @@
${session.repositorySession.localRepository.basedir.absolutePath}${env.GLOBAL_MVN_SETTINGS}
+
+
-Dconscrypt-version=${conscrypt.version}
diff --git a/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/config/etc/jetty-with-custom-class.xml b/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/config/etc/jetty-with-custom-class.xml
index 9f336e1c76f..0cd29f9a536 100644
--- a/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/config/etc/jetty-with-custom-class.xml
+++ b/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/config/etc/jetty-with-custom-class.xml
@@ -67,10 +67,9 @@
org.eclipse.jetty.ee10.plus.webapp.PlusConfigurationorg.eclipse.jetty.ee10.plus.webapp.EnvConfigurationorg.eclipse.jetty.ee10.webapp.JmxConfiguration
- config.org.eclipse.jetty.ee10.websocket.server.JettyWebSocketConfiguration
- org.eclipse.jetty.websocket.jakarta.server.config.JakartaWebSocketConfiguration
+ org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketConfiguration
+ org.eclipse.jetty.ee10.websocket.jakarta.server.config.JakartaWebSocketConfigurationorg.eclipse.jetty.ee10.osgi.annotations.AnnotationConfiguration
- org.eclipse.jetty.ee10.osgi.boot.OSGiWebInfConfigurationorg.eclipse.jetty.ee10.osgi.boot.OSGiMetaInfConfiguration
diff --git a/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/java/org/eclipse/jetty/ee10/osgi/test/TestJettyOSGiBootWithBundle.java b/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/java/org/eclipse/jetty/ee10/osgi/test/TestJettyOSGiBootWithBundle.java
new file mode 100644
index 00000000000..642af5489a4
--- /dev/null
+++ b/jetty-ee10/jetty-ee10-osgi/test-jetty-ee10-osgi/src/test/java/org/eclipse/jetty/ee10/osgi/test/TestJettyOSGiBootWithBundle.java
@@ -0,0 +1,123 @@
+//
+// ========================================================================
+// Copyright (c) 1995 Mort Bay Consulting Pty Ltd and others.
+//
+// This program and the accompanying materials are made available under the
+// terms of the Eclipse Public License v. 2.0 which is available at
+// https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
+// which is available at https://www.apache.org/licenses/LICENSE-2.0.
+//
+// SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
+// ========================================================================
+//
+
+package org.eclipse.jetty.ee10.osgi.test;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import javax.inject.Inject;
+
+import org.eclipse.jetty.client.ContentResponse;
+import org.eclipse.jetty.client.HttpClient;
+import org.eclipse.jetty.http.HttpStatus;
+import org.eclipse.jetty.osgi.OSGiServerConstants;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.tinybundles.core.TinyBundle;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+
+/**
+ * TestJettyOSGiBootWithBundle
+ *
+ * Tests reading config from a bundle and loading classes from it
+ *
+ * Tests the ServiceContextProvider.
+ */
+@RunWith(PaxExam.class)
+public class TestJettyOSGiBootWithBundle
+{
+ private static final String TEST_JETTY_HOME_BUNDLE = "test-jetty-xml-bundle";
+
+ @Inject
+ BundleContext bundleContext = null;
+
+ @Configuration
+ public static Option[] configure() throws IOException
+ {
+ ArrayList