Merge remote-tracking branch 'origin/jetty-10.0.x' into jetty-11.0.x

This commit is contained in:
Jan Bartel 2020-07-14 14:19:50 +02:00
commit 0b57809c04
13 changed files with 167 additions and 47 deletions

View File

@ -372,7 +372,7 @@ public class HttpRequest implements Request
} }
@Override @Override
public HttpFields.Mutable getHeaders() public HttpFields getHeaders()
{ {
return headers; return headers;
} }

View File

@ -128,6 +128,12 @@ public class ServletHandler extends ScopedHandler
{ {
} }
@Override
public boolean isDumpable(Object o)
{
return !(o instanceof Holder || o instanceof BaseHolder || o instanceof FilterMapping || o instanceof ServletMapping);
}
@Override @Override
public void dump(Appendable out, String indent) throws IOException public void dump(Appendable out, String indent) throws IOException
{ {
@ -216,6 +222,13 @@ public class ServletHandler extends ScopedHandler
super.start(l); super.start(l);
} }
@Override
protected void stop(LifeCycle l) throws Exception
{
if (!(l instanceof Holder))
super.stop(l);
}
@Override @Override
protected synchronized void doStop() protected synchronized void doStop()
throws Exception throws Exception
@ -251,8 +264,12 @@ public class ServletHandler extends ScopedHandler
} }
//Retain only filters and mappings that were added using jetty api (ie Source.EMBEDDED) //Retain only filters and mappings that were added using jetty api (ie Source.EMBEDDED)
_filters = (FilterHolder[])LazyList.toArray(filterHolders, FilterHolder.class); FilterHolder[] fhs = (FilterHolder[])LazyList.toArray(filterHolders, FilterHolder.class);
_filterMappings = (FilterMapping[])LazyList.toArray(filterMappings, FilterMapping.class); updateBeans(_filters, fhs);
_filters = fhs;
FilterMapping[] fms = (FilterMapping[])LazyList.toArray(filterMappings, FilterMapping.class);
updateBeans(_filterMappings, fms);
_filterMappings = fms;
_matchAfterIndex = (_filterMappings == null || _filterMappings.length == 0 ? -1 : _filterMappings.length - 1); _matchAfterIndex = (_filterMappings == null || _filterMappings.length == 0 ? -1 : _filterMappings.length - 1);
_matchBeforeIndex = -1; _matchBeforeIndex = -1;
@ -287,8 +304,12 @@ public class ServletHandler extends ScopedHandler
} }
//Retain only Servlets and mappings added via jetty apis (ie Source.EMBEDDED) //Retain only Servlets and mappings added via jetty apis (ie Source.EMBEDDED)
_servlets = (ServletHolder[])LazyList.toArray(servletHolders, ServletHolder.class); ServletHolder[] shs = (ServletHolder[])LazyList.toArray(servletHolders, ServletHolder.class);
_servletMappings = (ServletMapping[])LazyList.toArray(servletMappings, ServletMapping.class); updateBeans(_servlets, shs);
_servlets = shs;
ServletMapping[] sms = (ServletMapping[])LazyList.toArray(servletMappings, ServletMapping.class);
updateBeans(_servletMappings, sms);
_servletMappings = sms;
if (_contextHandler != null) if (_contextHandler != null)
_contextHandler.contextDestroyed(); _contextHandler.contextDestroyed();
@ -312,7 +333,9 @@ public class ServletHandler extends ScopedHandler
listenerHolders.add(listener); listenerHolders.add(listener);
} }
} }
_listeners = (ListenerHolder[])LazyList.toArray(listenerHolders, ListenerHolder.class); ListenerHolder[] listeners = (ListenerHolder[])LazyList.toArray(listenerHolders, ListenerHolder.class);
updateBeans(_listeners, listeners);
_listeners = listeners;
//will be regenerated on next start //will be regenerated on next start
_filterPathMappings = null; _filterPathMappings = null;
@ -765,7 +788,7 @@ public class ServletHandler extends ScopedHandler
{ {
holder.setServletHandler(this); holder.setServletHandler(this);
} }
updateBeans(_listeners,listeners);
_listeners = listeners; _listeners = listeners;
} }
@ -1442,6 +1465,7 @@ public class ServletHandler extends ScopedHandler
*/ */
public void setFilterMappings(FilterMapping[] filterMappings) public void setFilterMappings(FilterMapping[] filterMappings)
{ {
updateBeans(_filterMappings,filterMappings);
_filterMappings = filterMappings; _filterMappings = filterMappings;
if (isStarted()) if (isStarted())
updateMappings(); updateMappings();
@ -1455,7 +1479,7 @@ public class ServletHandler extends ScopedHandler
{ {
holder.setServletHandler(this); holder.setServletHandler(this);
} }
updateBeans(_filters,holders);
_filters = holders; _filters = holders;
updateNameMappings(); updateNameMappings();
invalidateChainsCache(); invalidateChainsCache();
@ -1466,6 +1490,7 @@ public class ServletHandler extends ScopedHandler
*/ */
public void setServletMappings(ServletMapping[] servletMappings) public void setServletMappings(ServletMapping[] servletMappings)
{ {
updateBeans(_servletMappings,servletMappings);
_servletMappings = servletMappings; _servletMappings = servletMappings;
if (isStarted()) if (isStarted())
updateMappings(); updateMappings();
@ -1484,7 +1509,7 @@ public class ServletHandler extends ScopedHandler
{ {
holder.setServletHandler(this); holder.setServletHandler(this);
} }
updateBeans(_servlets,holders);
_servlets = holders; _servlets = holders;
updateNameMappings(); updateNameMappings();
invalidateChainsCache(); invalidateChainsCache();

View File

@ -18,9 +18,15 @@
package org.eclipse.jetty.servlet; package org.eclipse.jetty.servlet;
import java.util.ArrayList;
import java.util.EnumSet; import java.util.EnumSet;
import java.util.List;
import jakarta.servlet.DispatcherType; import jakarta.servlet.DispatcherType;
import jakarta.servlet.http.HttpSessionEvent;
import jakarta.servlet.http.HttpSessionListener;
import org.eclipse.jetty.http.pathmap.MappedResource;
import org.eclipse.jetty.util.component.Container;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -656,4 +662,72 @@ public class ServletHandlerTest
assertTrue(fh3 == mappings[5].getFilterHolder()); //isMatchAfter = true; assertTrue(fh3 == mappings[5].getFilterHolder()); //isMatchAfter = true;
assertTrue(pf == mappings[6].getFilterHolder()); //isMatchAfter = true; assertTrue(pf == mappings[6].getFilterHolder()); //isMatchAfter = true;
} }
@Test
public void testFiltersServletsListenersAsBeans() throws Exception
{
ServletContextHandler context = new ServletContextHandler();
ServletHandler handler = context.getServletHandler();
//test that filters, servlets and listeners are added as beans
//and thus reported in a Container.Listener
List<Object> addResults = new ArrayList<>();
List<Object> removeResults = new ArrayList<>();
handler.addEventListener(new Container.Listener()
{
@Override
public void beanAdded(Container parent, Object child)
{
addResults.add(child);
}
@Override
public void beanRemoved(Container parent, Object child)
{
removeResults.add(child);
}
});
handler.addFilter(fh1);
handler.addServlet(sh1);
ListenerHolder lh1 = new ListenerHolder(new Source(Source.Origin.DESCRIPTOR, "foo.xml"));
lh1.setInstance(new HttpSessionListener()
{
@Override
public void sessionDestroyed(HttpSessionEvent se)
{
}
@Override
public void sessionCreated(HttpSessionEvent se)
{
}
});
handler.addListener(lh1);
assertTrue(addResults.contains(fh1));
assertTrue(addResults.contains(sh1));
assertTrue(addResults.contains(lh1));
//test that servlets, filters and listeners are dumped, but
//not as beans
String dump = handler.dump();
dump = dump.substring(0, dump.indexOf("key:"));
assertFalse(dump.contains("+-")); //not dumped as beans
assertFalse(dump.contains("+=")); //not dumped as managed beans
assertFalse(dump.contains("+~")); //not dumped as unmanaged beans
assertFalse(dump.contains("+?")); //not dumped as auto beans
handler.setFilters(null);
handler.setServlets(null);
handler.setListeners(null);
//check they're removed as beans
assertTrue(removeResults.contains(fh1));
assertTrue(removeResults.contains(sh1));
assertTrue(removeResults.contains(lh1));
}
} }

View File

@ -80,7 +80,7 @@ import org.slf4j.LoggerFactory;
* </pre> * </pre>
*/ */
@ManagedObject("Implementation of Container and LifeCycle") @ManagedObject("Implementation of Container and LifeCycle")
public class ContainerLifeCycle extends AbstractLifeCycle implements Container, Destroyable, Dumpable public class ContainerLifeCycle extends AbstractLifeCycle implements Container, Destroyable, Dumpable.DumpableContainer
{ {
private static final Logger LOG = LoggerFactory.getLogger(ContainerLifeCycle.class); private static final Logger LOG = LoggerFactory.getLogger(ContainerLifeCycle.class);
private final List<Bean> _beans = new CopyOnWriteArrayList<>(); private final List<Bean> _beans = new CopyOnWriteArrayList<>();

View File

@ -189,6 +189,10 @@ public interface Dumpable
for (Iterator<Object> i = container.getBeans().iterator(); i.hasNext(); ) for (Iterator<Object> i = container.getBeans().iterator(); i.hasNext(); )
{ {
Object bean = i.next(); Object bean = i.next();
if (container instanceof DumpableContainer && !((DumpableContainer)container).isDumpable(bean))
continue; //won't be dumped as a child bean
String nextIndent = indent + ((i.hasNext() || !last) ? "| " : " "); String nextIndent = indent + ((i.hasNext() || !last) ? "| " : " ");
if (bean instanceof LifeCycle) if (bean instanceof LifeCycle)
{ {
@ -267,4 +271,19 @@ public interface Dumpable
Dumpable.dumpObjects(out, indent, object); Dumpable.dumpObjects(out, indent, object);
}; };
} }
/**
* DumpableContainer
*
* A Dumpable that is a container of beans can implement this
* interface to allow it to refine which of its beans can be
* dumped.
*/
public interface DumpableContainer extends Dumpable
{
default boolean isDumpable(Object o)
{
return true;
}
}
} }

View File

@ -38,7 +38,6 @@ import org.eclipse.jetty.client.api.Request;
import org.eclipse.jetty.client.api.Response; import org.eclipse.jetty.client.api.Response;
import org.eclipse.jetty.client.api.Result; import org.eclipse.jetty.client.api.Result;
import org.eclipse.jetty.http.HttpField; import org.eclipse.jetty.http.HttpField;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpScheme; import org.eclipse.jetty.http.HttpScheme;
import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.http.HttpStatus;
@ -154,22 +153,26 @@ public abstract class ClientUpgradeRequest extends HttpRequest implements Respon
public void setSubProtocols(String... protocols) public void setSubProtocols(String... protocols)
{ {
HttpFields.Mutable headers = getHeaders(); headers(headers ->
{
headers.remove(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL); headers.remove(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL);
for (String protocol : protocols) for (String protocol : protocols)
{ {
headers.add(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, protocol); headers.add(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, protocol);
} }
});
} }
public void setSubProtocols(List<String> protocols) public void setSubProtocols(List<String> protocols)
{ {
HttpFields.Mutable headers = getHeaders(); headers(headers ->
{
headers.remove(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL); headers.remove(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL);
for (String protocol : protocols) for (String protocol : protocols)
{ {
headers.add(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, protocol); headers.add(HttpHeader.SEC_WEBSOCKET_SUBPROTOCOL, protocol);
} }
});
} }
@Override @Override
@ -282,7 +285,7 @@ public abstract class ClientUpgradeRequest extends HttpRequest implements Respon
.collect(Collectors.joining(",")); .collect(Collectors.joining(","));
if (!StringUtil.isEmpty(extensionString)) if (!StringUtil.isEmpty(extensionString))
getHeaders().add(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, extensionString); headers(headers -> headers.add(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, extensionString));
// Notify the listener which may change the headers directly. // Notify the listener which may change the headers directly.
notifyUpgradeListeners((listener) -> listener.onHandshakeRequest(this)); notifyUpgradeListeners((listener) -> listener.onHandshakeRequest(this));

View File

@ -413,13 +413,12 @@ public class WebSocketNegotiationTest extends WebSocketTester
upgradeRequest.setSubProtocols("test"); upgradeRequest.setSubProtocols("test");
upgradeRequest.addExtensions("permessage-deflate;server_no_context_takeover"); upgradeRequest.addExtensions("permessage-deflate;server_no_context_takeover");
CompletableFuture<String> extensionHeader = new CompletableFuture<>();
upgradeRequest.addListener(new UpgradeListener() upgradeRequest.addListener(new UpgradeListener()
{ {
@Override @Override
public void onHandshakeRequest(HttpRequest request) public void onHandshakeRequest(HttpRequest request)
{ {
request.getHeaders().put(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, "permessage-deflate"); request.headers(headers -> headers.put(HttpHeader.SEC_WEBSOCKET_EXTENSIONS, "permessage-deflate"));
} }
}); });

View File

@ -33,7 +33,7 @@ import org.eclipse.jetty.websocket.core.client.UpgradeListener;
public class JsrUpgradeListener implements UpgradeListener public class JsrUpgradeListener implements UpgradeListener
{ {
private Configurator configurator; private final Configurator configurator;
public JsrUpgradeListener(Configurator configurator) public JsrUpgradeListener(Configurator configurator)
{ {
@ -46,7 +46,7 @@ public class JsrUpgradeListener implements UpgradeListener
if (configurator == null) if (configurator == null)
return; return;
HttpFields.Mutable fields = request.getHeaders(); HttpFields fields = request.getHeaders();
Map<String, List<String>> originalHeaders = new HashMap<>(); Map<String, List<String>> originalHeaders = new HashMap<>();
fields.forEach(field -> fields.forEach(field ->
{ {
@ -59,8 +59,11 @@ public class JsrUpgradeListener implements UpgradeListener
configurator.beforeRequest(originalHeaders); configurator.beforeRequest(originalHeaders);
// Reset headers on HttpRequest per configurator // Reset headers on HttpRequest per configurator
fields.clear(); request.headers(headers ->
originalHeaders.forEach(fields::put); {
headers.clear();
originalHeaders.forEach(headers::put);
});
} }
@Override @Override

View File

@ -30,7 +30,6 @@ import java.util.concurrent.CountDownLatch;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.BufferUtil;
import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.Callback;
@ -72,12 +71,14 @@ public class NetworkFuzzer extends Fuzzer.Adapter implements Fuzzer, AutoCloseab
this.upgradeRequest = new RawUpgradeRequest(client, wsURI); this.upgradeRequest = new RawUpgradeRequest(client, wsURI);
if (requestHeaders != null) if (requestHeaders != null)
{ {
HttpFields.Mutable fields = this.upgradeRequest.getHeaders(); this.upgradeRequest.headers(fields ->
{
requestHeaders.forEach((name, value) -> requestHeaders.forEach((name, value) ->
{ {
fields.remove(name); fields.remove(name);
fields.put(name, value); fields.put(name, value);
}); });
});
} }
this.client.start(); this.client.start();
this.generator = new UnitGenerator(Behavior.CLIENT); this.generator = new UnitGenerator(Behavior.CLIENT);

View File

@ -24,7 +24,6 @@ import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.eclipse.jetty.client.HttpResponse; import org.eclipse.jetty.client.HttpResponse;
import org.eclipse.jetty.http.HttpFields;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
import org.eclipse.jetty.http.HttpVersion; import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.io.EndPoint; import org.eclipse.jetty.io.EndPoint;
@ -49,18 +48,14 @@ public class JettyClientUpgradeRequest extends ClientUpgradeRequest
if (request != null) if (request != null)
{ {
// Copy request details into actual request // Copy request details into actual request
HttpFields.Mutable fields = getHeaders(); headers(fields -> request.getHeaders().forEach(fields::put));
request.getHeaders().forEach(fields::put);
// Copy manually created Cookies into place // Copy manually created Cookies into place
List<HttpCookie> cookies = request.getCookies(); List<HttpCookie> cookies = request.getCookies();
if (cookies != null) if (cookies != null)
{ {
// TODO: remove existing Cookie header (if set)? // TODO: remove existing Cookie header (if set)?
for (HttpCookie cookie : cookies) headers(fields -> cookies.forEach(cookie -> fields.add(HttpHeader.COOKIE, cookie.toString())));
{
fields.add(HttpHeader.COOKIE, cookie.toString());
}
} }
// Copy sub-protocols // Copy sub-protocols

View File

@ -36,9 +36,9 @@ public class EchoSocket extends EventSocket
} }
@Override @Override
public void onMessage(byte[] buf, int offset, int len) public void onMessage(byte[] buf, int offset, int len) throws IOException
{ {
super.onMessage(buf, offset, len); super.onMessage(buf, offset, len);
session.getRemote().sendBytes(ByteBuffer.wrap(buf, offset, len), WriteCallback.NOOP); session.getRemote().sendBytes(ByteBuffer.wrap(buf, offset, len));
} }
} }

View File

@ -71,7 +71,7 @@ public class EventSocket
} }
@OnWebSocketMessage @OnWebSocketMessage
public void onMessage(byte[] buf, int offset, int len) public void onMessage(byte[] buf, int offset, int len) throws IOException
{ {
ByteBuffer message = ByteBuffer.wrap(buf, offset, len); ByteBuffer message = ByteBuffer.wrap(buf, offset, len);
if (LOG.isDebugEnabled()) if (LOG.isDebugEnabled())

View File

@ -403,6 +403,7 @@
</goals> </goals>
</execution> </execution>
</executions> </executions>
<!-- this has better support of gh token remove when with next release of jetty-version-maven-plugin -->
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.kohsuke</groupId> <groupId>org.kohsuke</groupId>