Merge remote-tracking branch 'origin/jetty-12.0.x' into jetty-12.1.x
This commit is contained in:
commit
ce13b8590f
|
@ -169,8 +169,9 @@ public class WebAppClassLoading
|
||||||
* Add a hidden (server) Class pattern to use for all WebAppContexts of a given {@link Server}.
|
* 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 attributes The {@link Attributes} instance to add classes to
|
||||||
* @param patterns the patterns to use
|
* @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)
|
public static void addHiddenClasses(Attributes attributes, String... patterns)
|
||||||
{
|
{
|
||||||
if (patterns != null && patterns.length > 0)
|
if (patterns != null && patterns.length > 0)
|
||||||
|
|
|
@ -22,6 +22,7 @@ import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
import org.eclipse.jetty.deploy.AppLifeCycle;
|
import org.eclipse.jetty.deploy.AppLifeCycle;
|
||||||
|
@ -195,13 +196,14 @@ public class JettyServerFactory
|
||||||
private static DeploymentManager ensureDeploymentManager(Server server)
|
private static DeploymentManager ensureDeploymentManager(Server server)
|
||||||
{
|
{
|
||||||
Collection<DeploymentManager> deployers = server.getBeans(DeploymentManager.class);
|
Collection<DeploymentManager> deployers = server.getBeans(DeploymentManager.class);
|
||||||
DeploymentManager deploymentManager;
|
DeploymentManager deploymentManager = null;
|
||||||
|
|
||||||
if (deployers != null)
|
if (deployers != null)
|
||||||
{
|
{
|
||||||
deploymentManager = deployers.stream().findFirst().get();
|
deploymentManager = deployers.stream().findFirst().orElse(null);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
if (deploymentManager == null)
|
||||||
{
|
{
|
||||||
deploymentManager = new DeploymentManager();
|
deploymentManager = new DeploymentManager();
|
||||||
deploymentManager.setContexts(getContextHandlerCollection(server));
|
deploymentManager.setContexts(getContextHandlerCollection(server));
|
||||||
|
|
|
@ -21,7 +21,6 @@ import java.util.Deque;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.atomic.AtomicReference;
|
import java.util.concurrent.atomic.AtomicReference;
|
||||||
import java.util.function.Consumer;
|
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.HttpHeader;
|
||||||
import org.eclipse.jetty.http.HttpStatus;
|
import org.eclipse.jetty.http.HttpStatus;
|
||||||
import org.eclipse.jetty.http.QuotedCSV;
|
import org.eclipse.jetty.http.QuotedCSV;
|
||||||
|
import org.eclipse.jetty.io.Retainable;
|
||||||
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
|
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
|
||||||
import org.eclipse.jetty.server.Handler;
|
import org.eclipse.jetty.server.Handler;
|
||||||
import org.eclipse.jetty.server.Request;
|
import org.eclipse.jetty.server.Request;
|
||||||
|
@ -68,7 +68,7 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
|
||||||
|
|
||||||
private final boolean _rfc7239;
|
private final boolean _rfc7239;
|
||||||
private final String _forwardedHeader;
|
private final String _forwardedHeader;
|
||||||
private final ConcurrentMap<String, Remote> _remotes = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, Remote> _remotes = new ConcurrentHashMap<>();
|
||||||
private volatile boolean _enabled;
|
private volatile boolean _enabled;
|
||||||
private int _threadLimit = 10;
|
private int _threadLimit = 10;
|
||||||
|
|
||||||
|
@ -163,7 +163,10 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
|
||||||
}
|
}
|
||||||
|
|
||||||
// We accept the request and will always handle it.
|
// 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();
|
limitedRequest.handle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -177,7 +180,8 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
|
||||||
private Remote getRemote(Request baseRequest)
|
private Remote getRemote(Request baseRequest)
|
||||||
{
|
{
|
||||||
String ip = getRemoteIP(baseRequest);
|
String ip = getRemoteIP(baseRequest);
|
||||||
LOG.debug("ip={}", ip);
|
if (LOG.isDebugEnabled())
|
||||||
|
LOG.debug("ip={}", ip);
|
||||||
if (ip == null)
|
if (ip == null)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
|
@ -185,15 +189,18 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
|
||||||
if (limit <= 0)
|
if (limit <= 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Remote remote = _remotes.get(ip);
|
// Use a compute method to create or retain the Remote instance as it is necessary for
|
||||||
if (remote == null)
|
// 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);
|
if (v != null)
|
||||||
remote = _remotes.putIfAbsent(ip, r);
|
{
|
||||||
if (remote == null)
|
v._referenceCounter.retain();
|
||||||
remote = r;
|
return v;
|
||||||
}
|
}
|
||||||
return remote;
|
return new Remote(baseRequest.getContext(), k, limit);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected String getRemoteIP(Request baseRequest)
|
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
|
// 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!
|
// RequestCustomizer!
|
||||||
if (baseRequest.getConnectionMetaData().getRemoteSocketAddress() instanceof InetSocketAddress inetAddr)
|
if (baseRequest.getConnectionMetaData().getRemoteSocketAddress() instanceof InetSocketAddress inetAddr)
|
||||||
{
|
{
|
||||||
|
@ -255,7 +262,12 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
|
||||||
int comma = forwardedFor.lastIndexOf(',');
|
int comma = forwardedFor.lastIndexOf(',');
|
||||||
return (comma >= 0) ? forwardedFor.substring(comma + 1).trim() : forwardedFor;
|
return (comma >= 0) ? forwardedFor.substring(comma + 1).trim() : forwardedFor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int getRemoteCount()
|
||||||
|
{
|
||||||
|
return _remotes.size();
|
||||||
|
}
|
||||||
|
|
||||||
private static class LimitedRequest extends Request.Wrapper
|
private static class LimitedRequest extends Request.Wrapper
|
||||||
{
|
{
|
||||||
private final Remote _remote;
|
private final Remote _remote;
|
||||||
|
@ -517,6 +529,7 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
|
||||||
private static final class Remote
|
private static final class Remote
|
||||||
{
|
{
|
||||||
private final Executor _executor;
|
private final Executor _executor;
|
||||||
|
private final Retainable.ReferenceCounter _referenceCounter = new Retainable.ReferenceCounter();
|
||||||
private final String _ip;
|
private final String _ip;
|
||||||
private final int _limit;
|
private final int _limit;
|
||||||
private final AutoLock _lock = new AutoLock();
|
private final AutoLock _lock = new AutoLock();
|
||||||
|
|
|
@ -104,6 +104,8 @@ public class ThreadLimitHandlerTest
|
||||||
last.set(null);
|
last.set(null);
|
||||||
_local.getResponse("GET / HTTP/1.0\r\nForwarded: for=1.2.3.4\r\n\r\n");
|
_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"));
|
assertThat(last.get(), is("0.0.0.0"));
|
||||||
|
|
||||||
|
await().atMost(5, TimeUnit.SECONDS).until(handler::getRemoteCount, is(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -147,6 +149,8 @@ public class ThreadLimitHandlerTest
|
||||||
last.set(null);
|
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");
|
_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"));
|
assertThat(last.get(), is("1.2.3.4"));
|
||||||
|
|
||||||
|
await().atMost(5, TimeUnit.SECONDS).until(handler::getRemoteCount, is(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -190,6 +194,8 @@ public class ThreadLimitHandlerTest
|
||||||
last.set(null);
|
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");
|
_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"));
|
assertThat(last.get(), is("1.2.3.4"));
|
||||||
|
|
||||||
|
await().atMost(5, TimeUnit.SECONDS).until(handler::getRemoteCount, is(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -248,6 +254,8 @@ public class ThreadLimitHandlerTest
|
||||||
|
|
||||||
await().atMost(10, TimeUnit.SECONDS).until(total::get, is(10));
|
await().atMost(10, TimeUnit.SECONDS).until(total::get, is(10));
|
||||||
await().atMost(10, TimeUnit.SECONDS).until(count::get, is(0));
|
await().atMost(10, TimeUnit.SECONDS).until(count::get, is(0));
|
||||||
|
|
||||||
|
await().atMost(5, TimeUnit.SECONDS).until(handler::getRemoteCount, is(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -367,5 +375,7 @@ public class ThreadLimitHandlerTest
|
||||||
assertThat(response, containsString(" 200 OK"));
|
assertThat(response, containsString(" 200 OK"));
|
||||||
assertThat(response, containsString(" read 2"));
|
assertThat(response, containsString(" read 2"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await().atMost(5, TimeUnit.SECONDS).until(handler::getRemoteCount, is(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -86,6 +86,22 @@
|
||||||
</plugins>
|
</plugins>
|
||||||
</build>
|
</build>
|
||||||
</profile>
|
</profile>
|
||||||
|
<profile>
|
||||||
|
<id>enable-foreign</id>
|
||||||
|
<activation>
|
||||||
|
<jdk>[22,)</jdk>
|
||||||
|
</activation>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<argLine>@{argLine} ${jetty.surefire.argLine} --enable-native-access=ALL-UNNAMED</argLine>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</profile>
|
||||||
</profiles>
|
</profiles>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1063,9 +1063,7 @@ public class HttpClientStreamTest extends AbstractTest
|
||||||
@MethodSource("transports")
|
@MethodSource("transports")
|
||||||
public void testUploadWithPendingReadConcurrentServerCloseClosesStream(Transport transport) throws Exception
|
public void testUploadWithPendingReadConcurrentServerCloseClosesStream(Transport transport) throws Exception
|
||||||
{
|
{
|
||||||
CountDownLatch serverDemandLatch = new CountDownLatch(1);
|
|
||||||
CountDownLatch serverLatch = new CountDownLatch(1);
|
CountDownLatch serverLatch = new CountDownLatch(1);
|
||||||
AtomicReference<Content.Chunk> lastChunk = new AtomicReference<>();
|
|
||||||
start(transport, new Handler.Abstract()
|
start(transport, new Handler.Abstract()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
|
@ -1076,16 +1074,14 @@ public class HttpClientStreamTest extends AbstractTest
|
||||||
@Override
|
@Override
|
||||||
public void run()
|
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();
|
Content.Chunk chunk = request.read();
|
||||||
if (chunk != null)
|
if (chunk != null)
|
||||||
chunk.release();
|
chunk.release();
|
||||||
if (chunk == null || !chunk.isLast())
|
if (chunk == null || !chunk.isLast())
|
||||||
{
|
|
||||||
request.demand(this);
|
request.demand(this);
|
||||||
return;
|
|
||||||
}
|
|
||||||
lastChunk.set(chunk);
|
|
||||||
serverDemandLatch.countDown();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
serverLatch.countDown();
|
serverLatch.countDown();
|
||||||
|
@ -1149,9 +1145,6 @@ public class HttpClientStreamTest extends AbstractTest
|
||||||
|
|
||||||
assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
|
assertTrue(completeLatch.await(5, TimeUnit.SECONDS));
|
||||||
assertTrue(closeLatch.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
|
@ParameterizedTest
|
||||||
|
|
|
@ -21,7 +21,7 @@ public interface ClassVisibilityChecker
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Is the class a Protected (System) Class.
|
* 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
|
* but that cannot be overridden by the contents of WEB-INF/lib or
|
||||||
* WEB-INF/classes
|
* WEB-INF/classes
|
||||||
*
|
*
|
||||||
|
@ -33,8 +33,8 @@ public interface ClassVisibilityChecker
|
||||||
/**
|
/**
|
||||||
* Is the class a Hidden (Server) Class.
|
* Is the class a Hidden (Server) Class.
|
||||||
* A Server class is a class that is part of the implementation of
|
* A Server class is a class that is part of the implementation of
|
||||||
* the server and is NIT visible to a webapplication. The web
|
* the server and is NOT visible to a web application. The web
|
||||||
* application may provide it's own implementation of the class,
|
* application may provide its own implementation of the class,
|
||||||
* to be loaded from WEB-INF/lib or WEB-INF/classes
|
* to be loaded from WEB-INF/lib or WEB-INF/classes
|
||||||
*
|
*
|
||||||
* @param clazz The fully qualified name of the class.
|
* @param clazz The fully qualified name of the class.
|
||||||
|
@ -44,7 +44,7 @@ public interface ClassVisibilityChecker
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is the class a System Class.
|
* 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
|
* but that cannot be overridden by the contents of WEB-INF/lib or
|
||||||
* WEB-INF/classes
|
* WEB-INF/classes
|
||||||
*
|
*
|
||||||
|
@ -61,8 +61,8 @@ public interface ClassVisibilityChecker
|
||||||
/**
|
/**
|
||||||
* Is the class a Server Class.
|
* Is the class a Server Class.
|
||||||
* A Server class is a class that is part of the implementation of
|
* A Server class is a class that is part of the implementation of
|
||||||
* the server and is NIT visible to a webapplication. The web
|
* the server and is NOT visible to a web application. The web
|
||||||
* application may provide it's own implementation of the class,
|
* application may provide its own implementation of the class,
|
||||||
* to be loaded from WEB-INF/lib or WEB-INF/classes
|
* to be loaded from WEB-INF/lib or WEB-INF/classes
|
||||||
*
|
*
|
||||||
* @param clazz The fully qualified name of the class.
|
* @param clazz The fully qualified name of the class.
|
||||||
|
|
|
@ -13,8 +13,6 @@
|
||||||
|
|
||||||
package org.eclipse.jetty.ee10.cdi;
|
package org.eclipse.jetty.ee10.cdi;
|
||||||
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.ee10.annotations.AnnotationConfiguration;
|
import org.eclipse.jetty.ee10.annotations.AnnotationConfiguration;
|
||||||
import org.eclipse.jetty.ee10.plus.webapp.PlusConfiguration;
|
import org.eclipse.jetty.ee10.plus.webapp.PlusConfiguration;
|
||||||
import org.eclipse.jetty.ee10.webapp.AbstractConfiguration;
|
import org.eclipse.jetty.ee10.webapp.AbstractConfiguration;
|
||||||
|
@ -33,11 +31,11 @@ public class CdiConfiguration extends AbstractConfiguration
|
||||||
{
|
{
|
||||||
super(new Builder()
|
super(new Builder()
|
||||||
.protectAndExpose("org.eclipse.jetty.ee10.cdi.CdiServletContainerInitializer")
|
.protectAndExpose("org.eclipse.jetty.ee10.cdi.CdiServletContainerInitializer")
|
||||||
.hide(getHiddenClasses())
|
.hide(getCdiHiddenClasses())
|
||||||
.addDependents(AnnotationConfiguration.class, PlusConfiguration.class));
|
.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
|
//Only hide the cdi api classes if there is not also an impl on the
|
||||||
//environment classpath - vital for embedded uses.
|
//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[]{"jakarta.enterprise.", "jakarta.decorator."};
|
||||||
return new String[0];
|
return new String[0];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd">
|
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||||
|
|
||||||
<!-- Weld needs access to some internal classes. Same configuration as "cdi2" module provides on server. -->
|
<!-- Weld needs access to some internal classes. Same configuration as "cdi2" module provides on server. -->
|
||||||
|
|
||||||
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
|
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
|
||||||
<Call name="addServerClassMatcher">
|
<Call name="addHiddenClassMatcher">
|
||||||
<Arg>
|
<Arg>
|
||||||
<New class="org.eclipse.jetty.util.ClassMatcher">
|
<New class="org.eclipse.jetty.util.ClassMatcher">
|
||||||
<Arg>
|
<Arg>
|
||||||
|
|
|
@ -42,6 +42,10 @@
|
||||||
</exclusion>
|
</exclusion>
|
||||||
</exclusions>
|
</exclusions>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.eclipse.jetty</groupId>
|
||||||
|
<artifactId>jetty-slf4j-impl</artifactId>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty.ee10.demos</groupId>
|
<groupId>org.eclipse.jetty.ee10.demos</groupId>
|
||||||
<artifactId>jetty-ee10-demo-mock-resources</artifactId>
|
<artifactId>jetty-ee10-demo-mock-resources</artifactId>
|
||||||
|
@ -263,18 +267,6 @@
|
||||||
<artifactId>jetty-alpn-server</artifactId>
|
<artifactId>jetty-alpn-server</artifactId>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<!--
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.slf4j</groupId>
|
|
||||||
<artifactId>slf4j-simple</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.eclipse.jetty</groupId>
|
|
||||||
<artifactId>jetty-slf4j-impl</artifactId>
|
|
||||||
<scope>test</scope>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.eclipse.jetty.ee10.demos</groupId>
|
<groupId>org.eclipse.jetty.ee10.demos</groupId>
|
||||||
<artifactId>jetty-ee10-demo-container-initializer</artifactId>
|
<artifactId>jetty-ee10-demo-container-initializer</artifactId>
|
||||||
|
@ -539,6 +531,8 @@
|
||||||
<systemPropertyVariables>
|
<systemPropertyVariables>
|
||||||
<mavenRepoPath>${session.repositorySession.localRepository.basedir.absolutePath}</mavenRepoPath>
|
<mavenRepoPath>${session.repositorySession.localRepository.basedir.absolutePath}</mavenRepoPath>
|
||||||
<settingsFilePath>${env.GLOBAL_MVN_SETTINGS}</settingsFilePath>
|
<settingsFilePath>${env.GLOBAL_MVN_SETTINGS}</settingsFilePath>
|
||||||
|
<!-- uncomment to be able to use jetty logging -->
|
||||||
|
<!-- pax.exam.system>default</pax.exam.system -->
|
||||||
</systemPropertyVariables>
|
</systemPropertyVariables>
|
||||||
<argLine>-Dconscrypt-version=${conscrypt.version}</argLine>
|
<argLine>-Dconscrypt-version=${conscrypt.version}</argLine>
|
||||||
<!-- TODO -->
|
<!-- TODO -->
|
||||||
|
|
|
@ -67,10 +67,9 @@
|
||||||
<Item>org.eclipse.jetty.ee10.plus.webapp.PlusConfiguration</Item>
|
<Item>org.eclipse.jetty.ee10.plus.webapp.PlusConfiguration</Item>
|
||||||
<Item>org.eclipse.jetty.ee10.plus.webapp.EnvConfiguration</Item>
|
<Item>org.eclipse.jetty.ee10.plus.webapp.EnvConfiguration</Item>
|
||||||
<Item>org.eclipse.jetty.ee10.webapp.JmxConfiguration</Item>
|
<Item>org.eclipse.jetty.ee10.webapp.JmxConfiguration</Item>
|
||||||
<Item>config.org.eclipse.jetty.ee10.websocket.server.JettyWebSocketConfiguration</Item>
|
<Item>org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketConfiguration</Item>
|
||||||
<Item>org.eclipse.jetty.websocket.jakarta.server.config.JakartaWebSocketConfiguration</Item>
|
<Item>org.eclipse.jetty.ee10.websocket.jakarta.server.config.JakartaWebSocketConfiguration</Item>
|
||||||
<Item>org.eclipse.jetty.ee10.osgi.annotations.AnnotationConfiguration</Item>
|
<Item>org.eclipse.jetty.ee10.osgi.annotations.AnnotationConfiguration</Item>
|
||||||
<Item>org.eclipse.jetty.ee10.osgi.boot.OSGiWebInfConfiguration</Item>
|
|
||||||
<Item>org.eclipse.jetty.ee10.osgi.boot.OSGiMetaInfConfiguration</Item>
|
<Item>org.eclipse.jetty.ee10.osgi.boot.OSGiMetaInfConfiguration</Item>
|
||||||
</Array>
|
</Array>
|
||||||
</Arg>
|
</Arg>
|
||||||
|
|
|
@ -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<Option> options = new ArrayList<>();
|
||||||
|
|
||||||
|
options.addAll(TestOSGiUtil.configurePaxExamLogging());
|
||||||
|
options.add(TestOSGiUtil.optionalRemoteDebug());
|
||||||
|
options.add(CoreOptions.junitBundles());
|
||||||
|
options.addAll(configureJettyHomeAndPort());
|
||||||
|
options.add(CoreOptions.bootDelegationPackages("org.xml.sax", "org.xml.*", "org.w3c.*", "javax.xml.*"));
|
||||||
|
options.add(CoreOptions.systemPackages("com.sun.org.apache.xalan.internal.res", "com.sun.org.apache.xml.internal.utils",
|
||||||
|
"com.sun.org.apache.xml.internal.utils", "com.sun.org.apache.xpath.internal",
|
||||||
|
"com.sun.org.apache.xpath.internal.jaxp", "com.sun.org.apache.xpath.internal.objects"));
|
||||||
|
TestOSGiUtil.coreJettyDependencies(options);
|
||||||
|
TestOSGiUtil.coreJspDependencies(options);
|
||||||
|
options.add(mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-alpn-java-client").versionAsInProject().start());
|
||||||
|
options.add(mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-alpn-client").versionAsInProject().start());
|
||||||
|
//back down version of bnd used here because tinybundles expects only this version
|
||||||
|
options.add(mavenBundle().groupId("biz.aQute.bnd").artifactId("biz.aQute.bndlib").version("3.5.0").start());
|
||||||
|
options.add(mavenBundle().groupId("org.ops4j.pax.tinybundles").artifactId("tinybundles").versionAsInProject().start());
|
||||||
|
TinyBundle bundle = TinyBundles.bundle();
|
||||||
|
bundle.add(SomeCustomBean.class);
|
||||||
|
bundle.set(Constants.BUNDLE_SYMBOLICNAME, TEST_JETTY_HOME_BUNDLE);
|
||||||
|
File etcFolder = new File("src/test/config/etc");
|
||||||
|
bundle.add("jettyhome/etc/jetty-http-boot-with-bundle.xml", new FileInputStream(new File(etcFolder, "jetty-http-boot-with-bundle.xml")));
|
||||||
|
bundle.add("jettyhome/etc/jetty-with-custom-class.xml", new FileInputStream(new File(etcFolder, "jetty-with-custom-class.xml")));
|
||||||
|
options.add(CoreOptions.streamBundle(bundle.build()).startLevel(1));
|
||||||
|
options.add(CoreOptions.cleanCaches(true));
|
||||||
|
return options.toArray(new Option[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<Option> configureJettyHomeAndPort()
|
||||||
|
{
|
||||||
|
List<Option> options = new ArrayList<>();
|
||||||
|
options.add(systemProperty(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS).value("etc/jetty-with-custom-class.xml,etc/jetty-http-boot-with-bundle.xml"));
|
||||||
|
options.add(systemProperty("jetty.http.port").value("0"));
|
||||||
|
// TODO: FIXME: options.add(systemProperty("jetty.ssl.port").value(String.valueOf(TestOSGiUtil.DEFAULT_SSL_PORT)));
|
||||||
|
options.add(systemProperty("jetty.home.bundle").value(TEST_JETTY_HOME_BUNDLE));
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testContextHandler() throws Exception
|
||||||
|
{
|
||||||
|
if (Boolean.getBoolean(TestOSGiUtil.BUNDLE_DEBUG))
|
||||||
|
TestOSGiUtil.diagnoseBundles(bundleContext);
|
||||||
|
|
||||||
|
// now test the context
|
||||||
|
HttpClient client = new HttpClient();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
client.start();
|
||||||
|
String tmp = System.getProperty("boot.bundle.port");
|
||||||
|
assertNotNull(tmp);
|
||||||
|
int port = Integer.valueOf(tmp.trim());
|
||||||
|
ContentResponse response = client.GET("http://127.0.0.1:" + port);
|
||||||
|
assertEquals(HttpStatus.NOT_FOUND_404, response.getStatus());
|
||||||
|
String content = new String(response.getContent());
|
||||||
|
assertNotNull(content);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
client.stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -153,41 +153,20 @@ public class TestOSGiUtil
|
||||||
res.add(systemProperty("org.ops4j.pax.url.mvn.settings").value(System.getProperty("settingsFilePath")));
|
res.add(systemProperty("org.ops4j.pax.url.mvn.settings").value(System.getProperty("settingsFilePath")));
|
||||||
}
|
}
|
||||||
|
|
||||||
res.add(mavenBundle().groupId("org.slf4j").artifactId("slf4j-api").versionAsInProject().noStart());
|
//configure jetty slf4j logging, and provide a jetty-logging properties file
|
||||||
|
//note 1: you will need to change the surefire plugin config in pom.xml to set the system property "pax.exam.system=false"
|
||||||
/*
|
//to make paxexam use this slf4j
|
||||||
* Jetty 11 uses slf4j 2.0.0 by default, however we want to test with slf4j 1.7.30 for backwards compatibility.
|
//note 2: if you do set the above system property, more than likely the test will not finish, no idea why
|
||||||
* To do that, we need to use slf4j-simple as the logging implementation. We make a simplelogger.properties
|
res.add(mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-slf4j-impl").versionAsInProject().start());
|
||||||
* file available so that jetty logging can be configured
|
res.add(mavenBundle().groupId("org.slf4j").artifactId("slf4j-api").versionAsInProject());
|
||||||
*/
|
|
||||||
// BEGIN - slf4j 1.7.x
|
|
||||||
/* slf4j-simple conflicts with both slf4j 1.7.x, and jetty-slf4j-impl. (but in different ways)
|
|
||||||
|
|
||||||
TinyBundle simpleLoggingPropertiesBundle = TinyBundles.bundle();
|
|
||||||
simpleLoggingPropertiesBundle.add("simplelogger.properties", ClassLoader.getSystemResource("simplelogger.properties"));
|
|
||||||
simpleLoggingPropertiesBundle.set(Constants.BUNDLE_SYMBOLICNAME, "simple-logger-properties");
|
|
||||||
simpleLoggingPropertiesBundle.set(Constants.FRAGMENT_HOST, "slf4j-simple");
|
|
||||||
simpleLoggingPropertiesBundle.add(FragmentActivator.class);
|
|
||||||
res.add(CoreOptions.streamBundle(simpleLoggingPropertiesBundle.build()).noStart());
|
|
||||||
res.add(mavenBundle().groupId("org.slf4j").artifactId("slf4j-simple").versionAsInProject().noStart());
|
|
||||||
*/
|
|
||||||
// END - slf4j 1.7.x
|
|
||||||
|
|
||||||
/*
|
|
||||||
* When running with slf4j >= 2.0.0, remove the slf4j simple logger above and uncomment the following lines
|
|
||||||
*/
|
|
||||||
// BEGIN - slf4j 2.x
|
|
||||||
TinyBundle loggingPropertiesBundle = TinyBundles.bundle();
|
TinyBundle loggingPropertiesBundle = TinyBundles.bundle();
|
||||||
loggingPropertiesBundle.add("jetty-logging.properties", ClassLoader.getSystemResource("jetty-logging.properties"));
|
loggingPropertiesBundle.add("jetty-logging.properties", ClassLoader.getSystemResource("jetty-logging.properties"));
|
||||||
loggingPropertiesBundle.set(Constants.BUNDLE_SYMBOLICNAME, "jetty-logging-properties");
|
loggingPropertiesBundle.set(Constants.BUNDLE_SYMBOLICNAME, "jetty-logging-properties");
|
||||||
loggingPropertiesBundle.set(Constants.FRAGMENT_HOST, "org.eclipse.jetty.logging");
|
loggingPropertiesBundle.set(Constants.FRAGMENT_HOST, "org.eclipse.jetty.logging");
|
||||||
loggingPropertiesBundle.add(FragmentActivator.class);
|
loggingPropertiesBundle.add(FragmentActivator.class);
|
||||||
res.add(CoreOptions.streamBundle(loggingPropertiesBundle.build()).noStart());
|
res.add(CoreOptions.streamBundle(loggingPropertiesBundle.build()).noStart());
|
||||||
res.add(mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-slf4j-impl").versionAsInProject().start());
|
|
||||||
// END - slf4j 2.x
|
|
||||||
|
|
||||||
res.add(mavenBundle().groupId("jakarta.el").artifactId("jakarta.el-api").versionAsInProject().start());
|
res.add(mavenBundle().groupId("jakarta.el").artifactId("jakarta.el-api").versionAsInProject().start());
|
||||||
|
|
||||||
res.add(mavenBundle().groupId("jakarta.servlet").artifactId("jakarta.servlet-api").versionAsInProject().start());
|
res.add(mavenBundle().groupId("jakarta.servlet").artifactId("jakarta.servlet-api").versionAsInProject().start());
|
||||||
res.add(mavenBundle().groupId("org.eclipse.platform").artifactId("org.eclipse.osgi.util").versionAsInProject());
|
res.add(mavenBundle().groupId("org.eclipse.platform").artifactId("org.eclipse.osgi.util").versionAsInProject());
|
||||||
res.add(mavenBundle().groupId("org.osgi").artifactId("org.osgi.service.cm").versionAsInProject());
|
res.add(mavenBundle().groupId("org.osgi").artifactId("org.osgi.service.cm").versionAsInProject());
|
||||||
|
|
|
@ -19,13 +19,15 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.ClassMatcher;
|
||||||
|
|
||||||
public class AbstractConfiguration implements Configuration
|
public class AbstractConfiguration implements Configuration
|
||||||
{
|
{
|
||||||
private final boolean _enabledByDefault;
|
private final boolean _enabledByDefault;
|
||||||
private final List<String> _after;
|
private final List<String> _after;
|
||||||
private final List<String> _before;
|
private final List<String> _before;
|
||||||
private final ClassMatcher _system;
|
private final ClassMatcher _protected;
|
||||||
private final ClassMatcher _server;
|
private final ClassMatcher _hidden;
|
||||||
|
|
||||||
public static class Builder
|
public static class Builder
|
||||||
{
|
{
|
||||||
|
@ -88,7 +90,7 @@ public class AbstractConfiguration implements Configuration
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protect classes from modification by the web application by adding them
|
* 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
|
* @param classes classname or package pattern
|
||||||
*/
|
*/
|
||||||
|
@ -100,7 +102,7 @@ public class AbstractConfiguration implements Configuration
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hide classes from the web application by adding them
|
* 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
|
* @param classes classname or package pattern
|
||||||
*/
|
*/
|
||||||
|
@ -112,7 +114,7 @@ public class AbstractConfiguration implements Configuration
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Expose classes to the web application by adding them
|
* 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
|
* @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
|
* 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
|
* 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
|
* @param classes classname or package pattern
|
||||||
*/
|
*/
|
||||||
|
@ -154,8 +156,8 @@ public class AbstractConfiguration implements Configuration
|
||||||
_enabledByDefault = builder._enabledByDefault;
|
_enabledByDefault = builder._enabledByDefault;
|
||||||
_after = List.copyOf(builder._after);
|
_after = List.copyOf(builder._after);
|
||||||
_before = List.copyOf(builder._before);
|
_before = List.copyOf(builder._before);
|
||||||
_system = new ClassMatcher(builder._system).asImmutable();
|
_protected = new ClassMatcher(builder._system).asImmutable();
|
||||||
_server = new ClassMatcher(builder._server).asImmutable();
|
_hidden = new ClassMatcher(builder._server).asImmutable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -171,15 +173,15 @@ public class AbstractConfiguration implements Configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassMatcher getSystemClasses()
|
public ClassMatcher getProtectedClasses()
|
||||||
{
|
{
|
||||||
return _system;
|
return _protected;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ClassMatcher getServerClasses()
|
public ClassMatcher getHiddenClasses()
|
||||||
{
|
{
|
||||||
return _server;
|
return _hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,7 +21,6 @@ import org.eclipse.jetty.util.IncludeExcludeSet;
|
||||||
/**
|
/**
|
||||||
* @deprecated Use org.eclipse.jetty.util.ClassMatcher
|
* @deprecated Use org.eclipse.jetty.util.ClassMatcher
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@Deprecated(since = "12.0.8", forRemoval = true)
|
||||||
public class ClassMatcher extends org.eclipse.jetty.util.ClassMatcher
|
public class ClassMatcher extends org.eclipse.jetty.util.ClassMatcher
|
||||||
{
|
{
|
||||||
|
|
|
@ -17,6 +17,7 @@ import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.ServiceLoader;
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
|
import org.eclipse.jetty.util.ClassMatcher;
|
||||||
import org.eclipse.jetty.util.TopologicalSort;
|
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
|
* (eg {@link JndiConfiguration}, {@link JaasConfiguration}} etc.) can be added or removed without concern
|
||||||
* for ordering.
|
* for ordering.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>Also since Jetty-9.4, Configurations are responsible for providing {@link #getServerClasses()} and
|
* <p>Also since Jetty-9.4, Configurations are responsible for providing {@link #getHiddenClasses()} and
|
||||||
* {@link #getSystemClasses()} to configure the {@link WebAppClassLoader} for each context.
|
* {@link #getProtectedClasses()} to configure the {@link WebAppClassLoader} for each context.
|
||||||
* </p>
|
* </p>
|
||||||
*/
|
*/
|
||||||
public interface Configuration
|
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.
|
* @return ClassMatcher of system classes.
|
||||||
*/
|
*/
|
||||||
default ClassMatcher getSystemClasses()
|
default ClassMatcher getProtectedClasses()
|
||||||
{
|
{
|
||||||
return new ClassMatcher();
|
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.
|
* @return ClassMatcher of server classes.
|
||||||
*/
|
*/
|
||||||
default ClassMatcher getServerClasses()
|
default ClassMatcher getHiddenClasses()
|
||||||
{
|
{
|
||||||
return new ClassMatcher();
|
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.
|
* Set up for configuration.
|
||||||
* <p>
|
* <p>
|
||||||
|
|
|
@ -111,9 +111,33 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility
|
||||||
|
|
||||||
List<Resource> getExtraClasspath();
|
List<Resource> getExtraClasspath();
|
||||||
|
|
||||||
boolean isHiddenResource(String name, URL parentUrl);
|
/**
|
||||||
|
* @deprecated use {@link #isHiddenResource(String, URL)}
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "12.0.8", forRemoval = true)
|
||||||
|
default boolean isServerResource(String name, URL parentUrl)
|
||||||
|
{
|
||||||
|
return isHiddenResource(name, parentUrl);
|
||||||
|
}
|
||||||
|
|
||||||
boolean isProtectedResource(String name, URL webappUrl);
|
/**
|
||||||
|
* @deprecated use {@link #isProtectedResource(String, URL)}
|
||||||
|
*/
|
||||||
|
@Deprecated(since = "12.0.8", forRemoval = true)
|
||||||
|
default boolean isSystemResource(String name, URL webappUrl)
|
||||||
|
{
|
||||||
|
return isProtectedResource(name, webappUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isHiddenResource(String name, URL parentUrl)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isProtectedResource(String name, URL webappUrl)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -521,7 +545,6 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility
|
||||||
|
|
||||||
if (webappUrl != null && (!checkSystemResource || !_context.isProtectedResource(name, webappUrl)))
|
if (webappUrl != null && (!checkSystemResource || !_context.isProtectedResource(name, webappUrl)))
|
||||||
{
|
{
|
||||||
|
|
||||||
webappClass = this.foundClass(name, webappUrl);
|
webappClass = this.foundClass(name, webappUrl);
|
||||||
resolveClass(webappClass);
|
resolveClass(webappClass);
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
|
|
|
@ -428,7 +428,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
// Add the known server class inclusions for all known configurations
|
// Add the known server class inclusions for all known configurations
|
||||||
for (Configuration configuration : Configurations.getKnown())
|
for (Configuration configuration : Configurations.getKnown())
|
||||||
{
|
{
|
||||||
_hiddenClasses.include(configuration.getServerClasses().getInclusions());
|
_hiddenClasses.include(configuration.getHiddenClasses().getInclusions());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Setup Configuration classes for this webapp!
|
// Setup Configuration classes for this webapp!
|
||||||
|
@ -436,8 +436,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
_configurations.sort();
|
_configurations.sort();
|
||||||
for (Configuration configuration : _configurations)
|
for (Configuration configuration : _configurations)
|
||||||
{
|
{
|
||||||
_protectedClasses.add(configuration.getSystemClasses().getPatterns());
|
_protectedClasses.add(configuration.getProtectedClasses().getPatterns());
|
||||||
_hiddenClasses.exclude(configuration.getServerClasses().getExclusions());
|
_hiddenClasses.exclude(configuration.getHiddenClasses().getExclusions());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configure classloader
|
// Configure classloader
|
||||||
|
@ -623,9 +623,9 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the hidden (aka server) classes patterns.
|
* Set the hidden (server) classes patterns.
|
||||||
* <p>
|
* <p>
|
||||||
* 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
|
* 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.
|
* own copy of them in WEB-INF/lib or WEB-INF/classes.
|
||||||
*
|
*
|
||||||
|
@ -638,7 +638,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the protected (aka system) classes patterns.
|
* Set the protected (system) classes patterns.
|
||||||
* <p>
|
* <p>
|
||||||
* These classes/packages are provided by the JVM and
|
* These classes/packages are provided by the JVM and
|
||||||
* cannot be replaced by classes of the same name from WEB-INF,
|
* cannot be replaced by classes of the same name from WEB-INF,
|
||||||
|
@ -683,7 +683,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()
|
public ClassMatcher getHiddenClassMatcher()
|
||||||
{
|
{
|
||||||
|
@ -696,7 +696,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
return _protectedClasses.getPatterns();
|
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()
|
public String[] getHiddenClasses()
|
||||||
{
|
{
|
||||||
return _hiddenClasses.getPatterns();
|
return _hiddenClasses.getPatterns();
|
||||||
|
@ -730,56 +730,54 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
* @deprecated use {@link #setHiddenClassMatcher(ClassMatcher)}
|
* @deprecated use {@link #setHiddenClassMatcher(ClassMatcher)}
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@Deprecated(since = "12.0.8", forRemoval = true)
|
||||||
public void setServerClassMatcher(ClassMatcher serverClasses)
|
public void setServerClassMatcher(org.eclipse.jetty.ee10.webapp.ClassMatcher serverClasses)
|
||||||
{
|
{
|
||||||
_hiddenClasses.clear();
|
setHiddenClassMatcher(serverClasses);
|
||||||
_hiddenClasses.add(serverClasses.getPatterns());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link #setProtectedClassMatcher(ClassMatcher)}
|
* @deprecated use {@link #setProtectedClassMatcher(ClassMatcher)}
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@Deprecated(since = "12.0.8", forRemoval = true)
|
||||||
public void setSystemClassMatcher(ClassMatcher systemClasses)
|
public void setSystemClassMatcher(org.eclipse.jetty.ee10.webapp.ClassMatcher systemClasses)
|
||||||
{
|
{
|
||||||
_protectedClasses.clear();
|
setProtectedClassMatcher(systemClasses);
|
||||||
_protectedClasses.add(systemClasses.getPatterns());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @deprecated use {@link #addHiddenClassMatcher(ClassMatcher)}
|
* @deprecated use {@link #addHiddenClassMatcher(ClassMatcher)}
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@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 use {@link #addProtectedClassMatcher(ClassMatcher)}
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@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 use {@link #getProtectedClassMatcher()}
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@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 use {@link #getHiddenClassMatcher()}
|
||||||
*/
|
*/
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@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());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -788,7 +786,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@Deprecated(since = "12.0.8", forRemoval = true)
|
||||||
public String[] getSystemClasses()
|
public String[] getSystemClasses()
|
||||||
{
|
{
|
||||||
return _protectedClasses.getPatterns();
|
return getProtectedClasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -797,7 +795,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@Deprecated(since = "12.0.8", forRemoval = true)
|
||||||
public String[] getServerClasses()
|
public String[] getServerClasses()
|
||||||
{
|
{
|
||||||
return _hiddenClasses.getPatterns();
|
return getHiddenClasses();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -806,7 +804,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@Deprecated(since = "12.0.8", forRemoval = true)
|
||||||
public boolean isServerClass(Class<?> clazz)
|
public boolean isServerClass(Class<?> clazz)
|
||||||
{
|
{
|
||||||
return _hiddenClasses.match(clazz);
|
return isHiddenClass(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -815,25 +813,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
@Deprecated(since = "12.0.8", forRemoval = true)
|
@Deprecated(since = "12.0.8", forRemoval = true)
|
||||||
public boolean isSystemClass(Class<?> clazz)
|
public boolean isSystemClass(Class<?> clazz)
|
||||||
{
|
{
|
||||||
return _protectedClasses.match(clazz);
|
return isProtectedClass(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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -75,7 +75,7 @@ public class WebAppClassLoaderTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void afterEach() throws Exception
|
public void afterEach()
|
||||||
{
|
{
|
||||||
IO.close(_loader);
|
IO.close(_loader);
|
||||||
LifeCycle.stop(_server);
|
LifeCycle.stop(_server);
|
||||||
|
@ -315,7 +315,6 @@ public class WebAppClassLoaderTest
|
||||||
|
|
||||||
resources = Collections.list(_loader.getResources("org/acme/resource.txt"));
|
resources = Collections.list(_loader.getResources("org/acme/resource.txt"));
|
||||||
|
|
||||||
expected.clear();
|
|
||||||
expected.add(webappWebInfLibAcme);
|
expected.add(webappWebInfLibAcme);
|
||||||
expected.add(webappWebInfClasses);
|
expected.add(webappWebInfClasses);
|
||||||
expected.add(targetTestClasses);
|
expected.add(targetTestClasses);
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd">
|
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||||
|
|
||||||
<!-- Weld needs access to some internal classes. Same configuration as "cdi2" module provides on server. -->
|
<!-- Weld needs access to some internal classes. Same configuration as "cdi2" module provides on server. -->
|
||||||
|
|
||||||
<Configure class="org.eclipse.jetty.ee8.webapp.WebAppContext">
|
<Configure class="org.eclipse.jetty.ee8.webapp.WebAppContext">
|
||||||
<Call name="addServerClassMatcher">
|
<Call name="addServerClassMatcher">
|
||||||
<Arg>
|
<Arg>
|
||||||
<New class="org.eclipse.jetty.util.ClassMatcher">
|
<New class="org.eclipse.jetty.ee8.webapp.ClassMatcher">
|
||||||
<Arg>
|
<Arg>
|
||||||
<Array type="java.lang.String">
|
<Array type="java.lang.String">
|
||||||
<Item>-org.eclipse.jetty.util.Decorator</Item>
|
<Item>-org.eclipse.jetty.util.Decorator</Item>
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||||
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_9_3.dtd">
|
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
|
||||||
|
|
||||||
<!-- Weld needs access to some internal classes. Same configuration as "cdi2" module provides on server. -->
|
<!-- Weld needs access to some internal classes. Same configuration as "cdi2" module provides on server. -->
|
||||||
|
|
||||||
<Configure class="org.eclipse.jetty.ee9.webapp.WebAppContext">
|
<Configure class="org.eclipse.jetty.ee9.webapp.WebAppContext">
|
||||||
<Call name="addServerClassMatcher">
|
<Call name="addServerClassMatcher">
|
||||||
<Arg>
|
<Arg>
|
||||||
<New class="org.eclipse.jetty.util.ClassMatcher">
|
<New class="org.eclipse.jetty.ee9.webapp.ClassMatcher">
|
||||||
<Arg>
|
<Arg>
|
||||||
<Array type="java.lang.String">
|
<Array type="java.lang.String">
|
||||||
<Item>-org.eclipse.jetty.util.Decorator</Item>
|
<Item>-org.eclipse.jetty.util.Decorator</Item>
|
||||||
|
|
|
@ -21,17 +21,19 @@ import java.util.ArrayDeque;
|
||||||
import java.util.Deque;
|
import java.util.Deque;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import jakarta.servlet.AsyncContext;
|
import jakarta.servlet.AsyncContext;
|
||||||
import jakarta.servlet.ServletException;
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.ServletRequestEvent;
|
||||||
|
import jakarta.servlet.ServletRequestListener;
|
||||||
import jakarta.servlet.http.HttpServletRequest;
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
import org.eclipse.jetty.http.HostPortHttpField;
|
import org.eclipse.jetty.http.HostPortHttpField;
|
||||||
import org.eclipse.jetty.http.HttpField;
|
import org.eclipse.jetty.http.HttpField;
|
||||||
import org.eclipse.jetty.http.HttpHeader;
|
import org.eclipse.jetty.http.HttpHeader;
|
||||||
import org.eclipse.jetty.http.QuotedCSV;
|
import org.eclipse.jetty.http.QuotedCSV;
|
||||||
|
import org.eclipse.jetty.io.Retainable;
|
||||||
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
|
import org.eclipse.jetty.server.ForwardedRequestCustomizer;
|
||||||
import org.eclipse.jetty.util.IncludeExcludeSet;
|
import org.eclipse.jetty.util.IncludeExcludeSet;
|
||||||
import org.eclipse.jetty.util.InetAddressSet;
|
import org.eclipse.jetty.util.InetAddressSet;
|
||||||
|
@ -72,7 +74,7 @@ public class ThreadLimitHandler extends HandlerWrapper
|
||||||
private final boolean _rfc7239;
|
private final boolean _rfc7239;
|
||||||
private final String _forwardedHeader;
|
private final String _forwardedHeader;
|
||||||
private final IncludeExcludeSet<String, InetAddress> _includeExcludeSet = new IncludeExcludeSet<>(InetAddressSet.class);
|
private final IncludeExcludeSet<String, InetAddress> _includeExcludeSet = new IncludeExcludeSet<>(InetAddressSet.class);
|
||||||
private final ConcurrentMap<String, Remote> _remotes = new ConcurrentHashMap<>();
|
private final ConcurrentHashMap<String, Remote> _remotes = new ConcurrentHashMap<>();
|
||||||
private volatile boolean _enabled;
|
private volatile boolean _enabled;
|
||||||
private int _threadLimit = 10;
|
private int _threadLimit = 10;
|
||||||
|
|
||||||
|
@ -178,6 +180,17 @@ public class ThreadLimitHandler extends HandlerWrapper
|
||||||
}
|
}
|
||||||
else
|
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?
|
// Do we already have a future permit from a previous invocation?
|
||||||
Closeable permit = (Closeable)baseRequest.getAttribute(PERMIT);
|
Closeable permit = (Closeable)baseRequest.getAttribute(PERMIT);
|
||||||
try
|
try
|
||||||
|
@ -249,14 +262,18 @@ public class ThreadLimitHandler extends HandlerWrapper
|
||||||
if (limit <= 0)
|
if (limit <= 0)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
remote = _remotes.get(ip);
|
// Use a compute method to create or retain the Remote instance as it is necessary for
|
||||||
if (remote == null)
|
// 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);
|
if (v != null)
|
||||||
remote = _remotes.putIfAbsent(ip, r);
|
{
|
||||||
if (remote == null)
|
v._referenceCounter.retain();
|
||||||
remote = r;
|
return v;
|
||||||
}
|
}
|
||||||
|
return new Remote(k, limit);
|
||||||
|
});
|
||||||
|
|
||||||
baseRequest.setAttribute(REMOTE, remote);
|
baseRequest.setAttribute(REMOTE, remote);
|
||||||
|
|
||||||
|
@ -325,6 +342,7 @@ public class ThreadLimitHandler extends HandlerWrapper
|
||||||
private final String _ip;
|
private final String _ip;
|
||||||
private final int _limit;
|
private final int _limit;
|
||||||
private final AutoLock _lock = new AutoLock();
|
private final AutoLock _lock = new AutoLock();
|
||||||
|
private final Retainable.ReferenceCounter _referenceCounter = new Retainable.ReferenceCounter();
|
||||||
private int _permits;
|
private int _permits;
|
||||||
private Deque<CompletableFuture<Closeable>> _queue = new ArrayDeque<>();
|
private Deque<CompletableFuture<Closeable>> _queue = new ArrayDeque<>();
|
||||||
private final CompletableFuture<Closeable> _permitted = CompletableFuture.completedFuture(this);
|
private final CompletableFuture<Closeable> _permitted = CompletableFuture.completedFuture(this);
|
||||||
|
|
|
@ -67,7 +67,7 @@
|
||||||
<Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item>
|
<Item>org.eclipse.jetty.plus.webapp.PlusConfiguration</Item>
|
||||||
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
|
<Item>org.eclipse.jetty.plus.webapp.EnvConfiguration</Item>
|
||||||
<Item>org.eclipse.jetty.ee9.webapp.JmxConfiguration</Item>
|
<Item>org.eclipse.jetty.ee9.webapp.JmxConfiguration</Item>
|
||||||
<Item>config.org.eclipse.jetty.ee10.websocket.server.JettyWebSocketConfiguration</Item>
|
<Item>org.eclipse.jetty.ee9.websocket.server.config.JettyWebSocketConfiguration</Item>
|
||||||
<Item>org.eclipse.jetty.websocket.jakarta.server.config.JakartaWebSocketConfiguration</Item>
|
<Item>org.eclipse.jetty.websocket.jakarta.server.config.JakartaWebSocketConfiguration</Item>
|
||||||
<Item>org.eclipse.jetty.ee9.osgi.annotations.AnnotationConfiguration</Item>
|
<Item>org.eclipse.jetty.ee9.osgi.annotations.AnnotationConfiguration</Item>
|
||||||
<Item>org.eclipse.jetty.ee9.osgi.boot.OSGiWebInfConfiguration</Item>
|
<Item>org.eclipse.jetty.ee9.osgi.boot.OSGiWebInfConfiguration</Item>
|
||||||
|
|
|
@ -18,11 +18,6 @@ import java.util.Map;
|
||||||
|
|
||||||
import org.eclipse.jetty.util.IncludeExcludeSet;
|
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 class ClassMatcher extends org.eclipse.jetty.util.ClassMatcher
|
||||||
{
|
{
|
||||||
public ClassMatcher()
|
public ClassMatcher()
|
||||||
|
|
|
@ -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.
|
* @return ClassMatcher of server classes.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -20,28 +20,24 @@ import java.lang.instrument.IllegalClassFormatException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLClassLoader;
|
import java.net.URLClassLoader;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.security.CodeSource;
|
import java.security.CodeSource;
|
||||||
import java.security.PermissionCollection;
|
import java.security.PermissionCollection;
|
||||||
import java.security.PrivilegedExceptionAction;
|
import java.security.PrivilegedExceptionAction;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.concurrent.CopyOnWriteArrayList;
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.eclipse.jetty.util.ClassVisibilityChecker;
|
import org.eclipse.jetty.util.ClassVisibilityChecker;
|
||||||
import org.eclipse.jetty.util.FileID;
|
import org.eclipse.jetty.util.FileID;
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
import org.eclipse.jetty.util.TypeUtil;
|
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.Resource;
|
||||||
import org.eclipse.jetty.util.resource.ResourceCollators;
|
import org.eclipse.jetty.util.resource.ResourceCollators;
|
||||||
import org.eclipse.jetty.util.resource.ResourceFactory;
|
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)))
|
if (webappUrl != null && (!checkSystemResource || !_context.isSystemResource(name, webappUrl)))
|
||||||
{
|
{
|
||||||
|
|
||||||
webappClass = this.foundClass(name, webappUrl);
|
webappClass = this.foundClass(name, webappUrl);
|
||||||
resolveClass(webappClass);
|
resolveClass(webappClass);
|
||||||
if (LOG.isDebugEnabled())
|
if (LOG.isDebugEnabled())
|
||||||
|
|
|
@ -55,7 +55,6 @@ import org.eclipse.jetty.server.Deployable;
|
||||||
import org.eclipse.jetty.server.Handler;
|
import org.eclipse.jetty.server.Handler;
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.util.Attributes;
|
import org.eclipse.jetty.util.Attributes;
|
||||||
import org.eclipse.jetty.util.ClassMatcher;
|
|
||||||
import org.eclipse.jetty.util.ExceptionUtil;
|
import org.eclipse.jetty.util.ExceptionUtil;
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.StringUtil;
|
import org.eclipse.jetty.util.StringUtil;
|
||||||
|
@ -673,7 +672,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
/**
|
/**
|
||||||
* Set the server classes patterns.
|
* Set the server classes patterns.
|
||||||
* <p>
|
* <p>
|
||||||
* 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
|
* 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.
|
* 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.
|
* Set the system classes patterns.
|
||||||
* <p>
|
* <p>
|
||||||
* 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,
|
* cannot be replaced by classes of the same name from WEB-INF,
|
||||||
* regardless of the value of {@link #setParentLoaderPriority(boolean)}.
|
* regardless of the value of {@link #setParentLoaderPriority(boolean)}.
|
||||||
*
|
*
|
||||||
|
@ -753,11 +752,23 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
||||||
@Override
|
@Override
|
||||||
public boolean isHiddenClass(Class<?> clazz)
|
public boolean isHiddenClass(Class<?> clazz)
|
||||||
{
|
{
|
||||||
return _serverClasses.match(clazz);
|
return isServerClass(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isProtectedClass(Class<?> clazz)
|
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);
|
return _systemClasses.match(clazz);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,6 @@ import java.util.List;
|
||||||
|
|
||||||
import org.eclipse.jetty.server.Server;
|
import org.eclipse.jetty.server.Server;
|
||||||
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
import org.eclipse.jetty.toolchain.test.MavenTestingUtils;
|
||||||
import org.eclipse.jetty.util.ClassMatcher;
|
|
||||||
import org.eclipse.jetty.util.IO;
|
import org.eclipse.jetty.util.IO;
|
||||||
import org.eclipse.jetty.util.component.LifeCycle;
|
import org.eclipse.jetty.util.component.LifeCycle;
|
||||||
import org.eclipse.jetty.util.resource.Resource;
|
import org.eclipse.jetty.util.resource.Resource;
|
||||||
|
@ -75,7 +74,7 @@ public class WebAppClassLoaderTest
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterEach
|
@AfterEach
|
||||||
public void afterEach() throws Exception
|
public void afterEach()
|
||||||
{
|
{
|
||||||
IO.close(_loader);
|
IO.close(_loader);
|
||||||
LifeCycle.stop(_server);
|
LifeCycle.stop(_server);
|
||||||
|
@ -315,7 +314,6 @@ public class WebAppClassLoaderTest
|
||||||
|
|
||||||
resources = Collections.list(_loader.getResources("org/acme/resource.txt"));
|
resources = Collections.list(_loader.getResources("org/acme/resource.txt"));
|
||||||
|
|
||||||
expected.clear();
|
|
||||||
expected.add(webappWebInfLibAcme);
|
expected.add(webappWebInfLibAcme);
|
||||||
expected.add(webappWebInfClasses);
|
expected.add(webappWebInfClasses);
|
||||||
expected.add(targetTestClasses);
|
expected.add(targetTestClasses);
|
||||||
|
|
Loading…
Reference in New Issue