diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ClassLoaderDump.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ClassLoaderDump.java deleted file mode 100644 index 7823100129f..00000000000 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/ClassLoaderDump.java +++ /dev/null @@ -1,26 +0,0 @@ -// -// ======================================================================== -// 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.server; - -/** - * @deprecated {@link org.eclipse.jetty.util.component.ClassLoaderDump} - */ -@Deprecated -public class ClassLoaderDump extends org.eclipse.jetty.util.component.ClassLoaderDump -{ - public ClassLoaderDump(ClassLoader loader) - { - super(loader); - } -} diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelListeners.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelListeners.java deleted file mode 100644 index e2760becd99..00000000000 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/HttpChannelListeners.java +++ /dev/null @@ -1,279 +0,0 @@ -// -// ======================================================================== -// 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.server; - -/** - * A HttpChannel.Listener that holds a collection of - * other HttpChannel.Listener instances that are efficiently - * invoked without iteration. - * @see AbstractConnector - */ -@Deprecated // TODO update or remove -public class HttpChannelListeners // TODO ??? implements HttpChannel.Listener -{ - /* TODO - static final Logger LOG = LoggerFactory.getLogger(HttpChannelListeners.class); - public static HttpChannel.Listener NOOP = new HttpChannel.Listener() {}; - - private final NotifyRequest onRequestBegin; - private final NotifyRequest onBeforeDispatch; - private final NotifyFailure onDispatchFailure; - private final NotifyRequest onAfterDispatch; - private final NotifyContent onRequestContent; - private final NotifyRequest onRequestContentEnd; - private final NotifyRequest onRequestTrailers; - private final NotifyRequest onRequestEnd; - private final NotifyFailure onRequestFailure; - private final NotifyRequest onResponseBegin; - private final NotifyRequest onResponseCommit; - private final NotifyContent onResponseContent; - private final NotifyRequest onResponseEnd; - private final NotifyFailure onResponseFailure; - private final NotifyRequest onComplete; - - public HttpChannelListeners(Collection listeners) - { - try - { - NotifyRequest onRequestBegin = NotifyRequest.NOOP; - NotifyRequest onBeforeDispatch = NotifyRequest.NOOP; - NotifyFailure onDispatchFailure = NotifyFailure.NOOP; - NotifyRequest onAfterDispatch = NotifyRequest.NOOP; - NotifyContent onRequestContent = NotifyContent.NOOP; - NotifyRequest onRequestContentEnd = NotifyRequest.NOOP; - NotifyRequest onRequestTrailers = NotifyRequest.NOOP; - NotifyRequest onRequestEnd = NotifyRequest.NOOP; - NotifyFailure onRequestFailure = NotifyFailure.NOOP; - NotifyRequest onResponseBegin = NotifyRequest.NOOP; - NotifyRequest onResponseCommit = NotifyRequest.NOOP; - NotifyContent onResponseContent = NotifyContent.NOOP; - NotifyRequest onResponseEnd = NotifyRequest.NOOP; - NotifyFailure onResponseFailure = NotifyFailure.NOOP; - NotifyRequest onComplete = NotifyRequest.NOOP; - - for (HttpChannel.Listener listener : listeners) - { - if (!listener.getClass().getMethod("onRequestBegin", Request.class).isDefault()) - onRequestBegin = combine(onRequestBegin, listener::onRequestBegin); - if (!listener.getClass().getMethod("onBeforeDispatch", Request.class).isDefault()) - onBeforeDispatch = combine(onBeforeDispatch, listener::onBeforeDispatch); - if (!listener.getClass().getMethod("onDispatchFailure", Request.class, Throwable.class).isDefault()) - onDispatchFailure = combine(onDispatchFailure, listener::onDispatchFailure); - if (!listener.getClass().getMethod("onAfterDispatch", Request.class).isDefault()) - onAfterDispatch = combine(onAfterDispatch, listener::onAfterDispatch); - if (!listener.getClass().getMethod("onRequestContent", Request.class, ByteBuffer.class).isDefault()) - onRequestContent = combine(onRequestContent, listener::onRequestContent); - if (!listener.getClass().getMethod("onRequestContentEnd", Request.class).isDefault()) - onRequestContentEnd = combine(onRequestContentEnd, listener::onRequestContentEnd); - if (!listener.getClass().getMethod("onRequestTrailers", Request.class).isDefault()) - onRequestTrailers = combine(onRequestTrailers, listener::onRequestTrailers); - if (!listener.getClass().getMethod("onRequestEnd", Request.class).isDefault()) - onRequestEnd = combine(onRequestEnd, listener::onRequestEnd); - if (!listener.getClass().getMethod("onRequestFailure", Request.class, Throwable.class).isDefault()) - onRequestFailure = combine(onRequestFailure, listener::onRequestFailure); - if (!listener.getClass().getMethod("onResponseBegin", Request.class).isDefault()) - onResponseBegin = combine(onResponseBegin, listener::onResponseBegin); - if (!listener.getClass().getMethod("onResponseCommit", Request.class).isDefault()) - onResponseCommit = combine(onResponseCommit, listener::onResponseCommit); - if (!listener.getClass().getMethod("onResponseContent", Request.class, ByteBuffer.class).isDefault()) - onResponseContent = combine(onResponseContent, listener::onResponseContent); - if (!listener.getClass().getMethod("onResponseEnd", Request.class).isDefault()) - onResponseEnd = combine(onResponseEnd, listener::onResponseEnd); - if (!listener.getClass().getMethod("onResponseFailure", Request.class, Throwable.class).isDefault()) - onResponseFailure = combine(onResponseFailure, listener::onResponseFailure); - if (!listener.getClass().getMethod("onComplete", Request.class).isDefault()) - onComplete = combine(onComplete, listener::onComplete); - } - - this.onRequestBegin = onRequestBegin; - this.onBeforeDispatch = onBeforeDispatch; - this.onDispatchFailure = onDispatchFailure; - this.onAfterDispatch = onAfterDispatch; - this.onRequestContent = onRequestContent; - this.onRequestContentEnd = onRequestContentEnd; - this.onRequestTrailers = onRequestTrailers; - this.onRequestEnd = onRequestEnd; - this.onRequestFailure = onRequestFailure; - this.onResponseBegin = onResponseBegin; - this.onResponseCommit = onResponseCommit; - this.onResponseContent = onResponseContent; - this.onResponseEnd = onResponseEnd; - this.onResponseFailure = onResponseFailure; - this.onComplete = onComplete; - } - catch (Exception e) - { - throw new RuntimeException(e); - } - } - - @Override - public void onRequestBegin(Request request) - { - onRequestBegin.onRequest(request); - } - - @Override - public void onBeforeDispatch(Request request) - { - onBeforeDispatch.onRequest(request); - } - - @Override - public void onDispatchFailure(Request request, Throwable failure) - { - onDispatchFailure.onFailure(request, failure); - } - - @Override - public void onAfterDispatch(Request request) - { - onAfterDispatch.onRequest(request); - } - - @Override - public void onRequestContent(Request request, ByteBuffer content) - { - onRequestContent.onContent(request, content); - } - - @Override - public void onRequestContentEnd(Request request) - { - onRequestContentEnd.onRequest(request); - } - - @Override - public void onRequestTrailers(Request request) - { - onRequestTrailers.onRequest(request); - } - - @Override - public void onRequestEnd(Request request) - { - onRequestEnd.onRequest(request); - } - - @Override - public void onRequestFailure(Request request, Throwable failure) - { - onRequestFailure.onFailure(request, failure); - } - - @Override - public void onResponseBegin(Request request) - { - onResponseBegin.onRequest(request); - } - - @Override - public void onResponseCommit(Request request) - { - onResponseCommit.onRequest(request); - } - - @Override - public void onResponseContent(Request request, ByteBuffer content) - { - onResponseContent.onContent(request, content); - } - - @Override - public void onResponseEnd(Request request) - { - onResponseEnd.onRequest(request); - } - - @Override - public void onResponseFailure(Request request, Throwable failure) - { - onResponseFailure.onFailure(request, failure); - } - - @Override - public void onComplete(Request request) - { - onComplete.onRequest(request); - } - - private interface NotifyRequest - { - void onRequest(Request request); - - NotifyRequest NOOP = request -> - { - }; - } - - private interface NotifyFailure - { - void onFailure(Request request, Throwable failure); - - NotifyFailure NOOP = (request, failure) -> - { - }; - } - - private interface NotifyContent - { - void onContent(Request request, ByteBuffer content); - - NotifyContent NOOP = (request, content) -> - { - }; - } - - private static NotifyRequest combine(NotifyRequest first, NotifyRequest second) - { - if (first == NotifyRequest.NOOP) - return second; - if (second == NotifyRequest.NOOP) - return first; - return request -> - { - first.onRequest(request); - second.onRequest(request); - }; - } - - private static NotifyFailure combine(NotifyFailure first, NotifyFailure second) - { - if (first == NotifyFailure.NOOP) - return second; - if (second == NotifyFailure.NOOP) - return first; - return (request, throwable) -> - { - first.onFailure(request, throwable); - second.onFailure(request, throwable); - }; - } - - private static NotifyContent combine(NotifyContent first, NotifyContent second) - { - if (first == NotifyContent.NOOP) - return (request, content) -> second.onContent(request, content.slice()); - if (second == NotifyContent.NOOP) - return (request, content) -> first.onContent(request, content.slice()); - return (request, content) -> - { - content = content.slice(); - first.onContent(request, content); - second.onContent(request, content); - }; - } - - */ -} diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java index 60a8b14e27b..37708bbd103 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/Server.java @@ -51,6 +51,8 @@ import org.eclipse.jetty.util.Uptime; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.Name; import org.eclipse.jetty.util.component.AttributeContainerMap; +import org.eclipse.jetty.util.component.ClassLoaderDump; +import org.eclipse.jetty.util.component.DumpableAttributes; import org.eclipse.jetty.util.component.DumpableCollection; import org.eclipse.jetty.util.component.Environment; import org.eclipse.jetty.util.component.Graceful; @@ -804,8 +806,10 @@ public class Server extends Handler.Wrapper implements Attributes @Override public void dump(Appendable out, String indent) throws IOException { - dumpObjects(out, indent, new org.eclipse.jetty.util.component.ClassLoaderDump(this.getClass().getClassLoader()), + dumpObjects(out, indent, + new ClassLoaderDump(this.getClass().getClassLoader()), new DumpableCollection("environments", Environment.getAll()), + new DumpableAttributes("attributes", _attributes), FileSystemPool.INSTANCE); } diff --git a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 70b40c30ad8..ced33a0e0e2 100644 --- a/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-core/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -52,7 +52,7 @@ import org.eclipse.jetty.util.TypeUtil; import org.eclipse.jetty.util.URIUtil; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.component.ClassLoaderDump; -import org.eclipse.jetty.util.component.Dumpable; +import org.eclipse.jetty.util.component.DumpableAttributes; import org.eclipse.jetty.util.component.LifeCycle; import org.eclipse.jetty.util.resource.Resource; import org.eclipse.jetty.util.resource.ResourceFactory; @@ -272,8 +272,8 @@ public class ContextHandler extends Handler.Wrapper implements Attributes, Alias { dumpObjects(out, indent, new ClassLoaderDump(getClassLoader()), - Dumpable.named("context " + this, _context), - Dumpable.named("handler attributes " + this, _persistentAttributes)); + new DumpableAttributes("handler attributes", _persistentAttributes), + new DumpableAttributes("attributes", _context)); } @ManagedAttribute(value = "Context") diff --git a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java index 4f5c0b4300f..def0c4bdc1c 100644 --- a/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java +++ b/jetty-core/jetty-server/src/test/java/org/eclipse/jetty/server/handler/ContextHandlerTest.java @@ -60,6 +60,7 @@ import org.eclipse.jetty.toolchain.test.MavenTestingUtils; import org.eclipse.jetty.util.BufferUtil; import org.eclipse.jetty.util.Callback; import org.eclipse.jetty.util.IO; +import org.eclipse.jetty.util.component.Dumpable; import org.eclipse.jetty.util.component.Graceful; import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterEach; @@ -1061,4 +1062,54 @@ public class ContextHandlerTest assertTrue(shutdown.isDone()); assertThat(gracefulHandler.getCurrentRequestCount(), is(0L)); } + + @Test + public void testContextDump() throws Exception + { + Server server = new Server(); + ContextHandler contextHandler = new ContextHandler("/ctx"); + server.setHandler(contextHandler); + contextHandler.setHandler(new Handler.Abstract() + { + @Override + public boolean handle(Request request, Response response, Callback callback) throws Exception + { + callback.succeeded(); + return true; + } + + @Override + public String toString() + { + return "TestHandler"; + } + }); + + contextHandler.setAttribute("name", "hidden"); + contextHandler.setAttribute("persistent1", "value1"); + contextHandler.setAttribute("persistent2", Dumpable.named("named", "value2")); + + server.start(); + + contextHandler.getContext().setAttribute("name", "override"); + contextHandler.getContext().setAttribute("transient1", "value1"); + contextHandler.getContext().setAttribute("transient2", Dumpable.named("named", "value2")); + + String dump = contextHandler.dump().replaceAll("\\r?\\n", "\n"); + assertThat(dump, containsString("oejsh.ContextHandler@")); + String expected = """ + +> No ClassLoader + +> handler attributes size=3 + | +> name: hidden + | +> persistent1: value1 + | +> persistent2: named: value2 + +> attributes size=5 + +> name: override + +> persistent1: value1 + +> persistent2: named: value2 + +> transient1: value1 + +> transient2: named: value2 + """; + assertThat(dump, containsString(expected)); + } } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java index ab1f8ed8bff..ace394b957c 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/Attributes.java @@ -64,63 +64,51 @@ public interface Attributes // TODO: change to getAttributeNames() once jetty-core is cleaned of servlet-api usages Set getAttributeNameSet(); - // TODO something better than this default Map asAttributeMap() { return new AbstractMap<>() { + private final Set _attributeNameSet = getAttributeNameSet(); + private final AbstractSet> _entrySet = new AbstractSet<>() + { + @Override + public Iterator> iterator() + { + Iterator names = _attributeNameSet.iterator(); + return new Iterator<>() + { + @Override + public boolean hasNext() + { + return names.hasNext(); + } + + @Override + public Entry next() + { + String name = names.next(); + return new SimpleEntry<>(name, getAttribute(name)); + } + }; + } + + @Override + public int size() + { + return _attributeNameSet.size(); + } + }; + + @Override + public int size() + { + return _attributeNameSet.size(); + } + @Override public Set> entrySet() { - return new AbstractSet<>() - { - Iterator names = getAttributeNameSet().iterator(); - - @Override - public Iterator> iterator() - { - return new Iterator<>() - { - @Override - public boolean hasNext() - { - return names.hasNext(); - } - - @Override - public Entry next() - { - String name = names.next(); - return new Map.Entry<>() - { - @Override - public String getKey() - { - return name; - } - - @Override - public Object getValue() - { - return getAttribute(name); - } - - @Override - public Object setValue(Object value) - { - throw new UnsupportedOperationException(); - } - }; - } - }; - } - - @Override - public int size() - { - return 0; - } - }; + return _entrySet; } }; } diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/component/DumpableAttributes.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/component/DumpableAttributes.java new file mode 100644 index 00000000000..1ce51d8d927 --- /dev/null +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/component/DumpableAttributes.java @@ -0,0 +1,40 @@ +// +// ======================================================================== +// 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.util.component; + +import java.io.IOException; +import java.util.Map; + +import org.eclipse.jetty.util.Attributes; + +public class DumpableAttributes implements Dumpable +{ + private final String _name; + private final Attributes _attributes; + + public DumpableAttributes(String name, Attributes attributes) + { + _name = name; + _attributes = attributes; + } + + @Override + public void dump(Appendable out, String indent) throws IOException + { + Object[] array = _attributes.asAttributeMap().entrySet().stream() + .sorted(Map.Entry.comparingByKey()) + .map(e -> Dumpable.named(e.getKey(), e.getValue())).toArray(Object[]::new); + Dumpable.dumpObjects(out, indent, _name + " size=" + array.length, array); + } +} diff --git a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/component/DumpableCollection.java b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/component/DumpableCollection.java index c4820498817..83cac168237 100644 --- a/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/component/DumpableCollection.java +++ b/jetty-core/jetty-util/src/main/java/org/eclipse/jetty/util/component/DumpableCollection.java @@ -44,12 +44,6 @@ public class DumpableCollection implements Dumpable return new DumpableCollection(name, collection); } - @Override - public String dump() - { - return Dumpable.dump(this); - } - @Override public void dump(Appendable out, String indent) throws IOException { @@ -57,3 +51,4 @@ public class DumpableCollection implements Dumpable Dumpable.dumpObjects(out, indent, _name + " size=" + (array == null ? 0 : array.length), array); } } +