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}.
|
||||
* @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)
|
||||
|
|
|
@ -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<DeploymentManager> 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));
|
||||
|
|
|
@ -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<String, Remote> _remotes = new ConcurrentHashMap<>();
|
||||
private final ConcurrentHashMap<String, Remote> _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,6 +180,7 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
|
|||
private Remote getRemote(Request baseRequest)
|
||||
{
|
||||
String ip = getRemoteIP(baseRequest);
|
||||
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;
|
||||
if (v != null)
|
||||
{
|
||||
v._referenceCounter.retain();
|
||||
return v;
|
||||
}
|
||||
return remote;
|
||||
return new Remote(baseRequest.getContext(), k, limit);
|
||||
});
|
||||
}
|
||||
|
||||
protected String getRemoteIP(Request baseRequest)
|
||||
|
@ -256,6 +263,11 @@ public class ThreadLimitHandler extends ConditionalHandler.Abstract
|
|||
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();
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -86,6 +86,22 @@
|
|||
</plugins>
|
||||
</build>
|
||||
</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>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -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<Content.Chunk> 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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?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. -->
|
||||
|
||||
<Configure class="org.eclipse.jetty.ee10.webapp.WebAppContext">
|
||||
<Call name="addServerClassMatcher">
|
||||
<Call name="addHiddenClassMatcher">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.util.ClassMatcher">
|
||||
<Arg>
|
||||
|
|
|
@ -42,6 +42,10 @@
|
|||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-slf4j-impl</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.jetty.ee10.demos</groupId>
|
||||
<artifactId>jetty-ee10-demo-mock-resources</artifactId>
|
||||
|
@ -263,18 +267,6 @@
|
|||
<artifactId>jetty-alpn-server</artifactId>
|
||||
<scope>test</scope>
|
||||
</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>
|
||||
<groupId>org.eclipse.jetty.ee10.demos</groupId>
|
||||
<artifactId>jetty-ee10-demo-container-initializer</artifactId>
|
||||
|
@ -539,6 +531,8 @@
|
|||
<systemPropertyVariables>
|
||||
<mavenRepoPath>${session.repositorySession.localRepository.basedir.absolutePath}</mavenRepoPath>
|
||||
<settingsFilePath>${env.GLOBAL_MVN_SETTINGS}</settingsFilePath>
|
||||
<!-- uncomment to be able to use jetty logging -->
|
||||
<!-- pax.exam.system>default</pax.exam.system -->
|
||||
</systemPropertyVariables>
|
||||
<argLine>-Dconscrypt-version=${conscrypt.version}</argLine>
|
||||
<!-- TODO -->
|
||||
|
|
|
@ -67,10 +67,9 @@
|
|||
<Item>org.eclipse.jetty.ee10.plus.webapp.PlusConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.ee10.plus.webapp.EnvConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.ee10.webapp.JmxConfiguration</Item>
|
||||
<Item>config.org.eclipse.jetty.ee10.websocket.server.JettyWebSocketConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.websocket.jakarta.server.config.JakartaWebSocketConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.ee10.websocket.server.config.JettyWebSocketConfiguration</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.boot.OSGiWebInfConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.ee10.osgi.boot.OSGiMetaInfConfiguration</Item>
|
||||
</Array>
|
||||
</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(mavenBundle().groupId("org.slf4j").artifactId("slf4j-api").versionAsInProject().noStart());
|
||||
|
||||
/*
|
||||
* Jetty 11 uses slf4j 2.0.0 by default, however we want to test with slf4j 1.7.30 for backwards compatibility.
|
||||
* To do that, we need to use slf4j-simple as the logging implementation. We make a simplelogger.properties
|
||||
* file available so that jetty logging can be configured
|
||||
*/
|
||||
// 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
|
||||
//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
|
||||
//note 2: if you do set the above system property, more than likely the test will not finish, no idea why
|
||||
res.add(mavenBundle().groupId("org.eclipse.jetty").artifactId("jetty-slf4j-impl").versionAsInProject().start());
|
||||
res.add(mavenBundle().groupId("org.slf4j").artifactId("slf4j-api").versionAsInProject());
|
||||
TinyBundle loggingPropertiesBundle = TinyBundles.bundle();
|
||||
loggingPropertiesBundle.add("jetty-logging.properties", ClassLoader.getSystemResource("jetty-logging.properties"));
|
||||
loggingPropertiesBundle.set(Constants.BUNDLE_SYMBOLICNAME, "jetty-logging-properties");
|
||||
loggingPropertiesBundle.set(Constants.FRAGMENT_HOST, "org.eclipse.jetty.logging");
|
||||
loggingPropertiesBundle.add(FragmentActivator.class);
|
||||
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.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.osgi").artifactId("org.osgi.service.cm").versionAsInProject());
|
||||
|
|
|
@ -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<String> _after;
|
||||
private final List<String> _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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
* </p>
|
||||
* <p>Also since Jetty-9.4, Configurations are responsible for providing {@link #getServerClasses()} and
|
||||
* {@link #getSystemClasses()} to configure the {@link WebAppClassLoader} for each context.
|
||||
* <p>Also since Jetty-9.4, Configurations are responsible for providing {@link #getHiddenClasses()} and
|
||||
* {@link #getProtectedClasses()} to configure the {@link WebAppClassLoader} for each context.
|
||||
* </p>
|
||||
*/
|
||||
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.
|
||||
* <p>
|
||||
|
|
|
@ -111,9 +111,33 @@ public class WebAppClassLoader extends URLClassLoader implements ClassVisibility
|
|||
|
||||
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)))
|
||||
{
|
||||
|
||||
webappClass = this.foundClass(name, webappUrl);
|
||||
resolveClass(webappClass);
|
||||
if (LOG.isDebugEnabled())
|
||||
|
|
|
@ -428,7 +428,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
// Add the known server class inclusions for all known configurations
|
||||
for (Configuration configuration : Configurations.getKnown())
|
||||
{
|
||||
_hiddenClasses.include(configuration.getServerClasses().getInclusions());
|
||||
_hiddenClasses.include(configuration.getHiddenClasses().getInclusions());
|
||||
}
|
||||
|
||||
// Setup Configuration classes for this webapp!
|
||||
|
@ -436,8 +436,8 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
_configurations.sort();
|
||||
for (Configuration configuration : _configurations)
|
||||
{
|
||||
_protectedClasses.add(configuration.getSystemClasses().getPatterns());
|
||||
_hiddenClasses.exclude(configuration.getServerClasses().getExclusions());
|
||||
_protectedClasses.add(configuration.getProtectedClasses().getPatterns());
|
||||
_hiddenClasses.exclude(configuration.getHiddenClasses().getExclusions());
|
||||
}
|
||||
|
||||
// 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>
|
||||
* 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.
|
||||
*
|
||||
|
@ -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>
|
||||
* These classes/packages are provided by the JVM and
|
||||
* 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()
|
||||
{
|
||||
|
@ -696,7 +696,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();
|
||||
|
@ -730,56 +730,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());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -788,7 +786,7 @@ public class WebAppContext extends ServletContextHandler implements WebAppClassL
|
|||
@Deprecated(since = "12.0.8", forRemoval = true)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<?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. -->
|
||||
|
||||
<Configure class="org.eclipse.jetty.ee8.webapp.WebAppContext">
|
||||
<Call name="addServerClassMatcher">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.util.ClassMatcher">
|
||||
<New class="org.eclipse.jetty.ee8.webapp.ClassMatcher">
|
||||
<Arg>
|
||||
<Array type="java.lang.String">
|
||||
<Item>-org.eclipse.jetty.util.Decorator</Item>
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<?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. -->
|
||||
|
||||
<Configure class="org.eclipse.jetty.ee9.webapp.WebAppContext">
|
||||
<Call name="addServerClassMatcher">
|
||||
<Arg>
|
||||
<New class="org.eclipse.jetty.util.ClassMatcher">
|
||||
<New class="org.eclipse.jetty.ee9.webapp.ClassMatcher">
|
||||
<Arg>
|
||||
<Array type="java.lang.String">
|
||||
<Item>-org.eclipse.jetty.util.Decorator</Item>
|
||||
|
|
|
@ -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<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 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<CompletableFuture<Closeable>> _queue = new ArrayDeque<>();
|
||||
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.EnvConfiguration</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.ee9.osgi.annotations.AnnotationConfiguration</Item>
|
||||
<Item>org.eclipse.jetty.ee9.osgi.boot.OSGiWebInfConfiguration</Item>
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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.
|
||||
* <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
|
||||
* 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.
|
||||
* <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,
|
||||
* 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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue