* Fix #9630 dumpable context Added DumpableAttributes utility class * fixed test format * Updates from review
This commit is contained in:
parent
64b54adb9c
commit
c2dc87c039
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<HttpChannel.Listener> 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);
|
||||
};
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,63 +64,51 @@ public interface Attributes
|
|||
// TODO: change to getAttributeNames() once jetty-core is cleaned of servlet-api usages
|
||||
Set<String> getAttributeNameSet();
|
||||
|
||||
// TODO something better than this
|
||||
default Map<String, Object> asAttributeMap()
|
||||
{
|
||||
return new AbstractMap<>()
|
||||
{
|
||||
private final Set<String> _attributeNameSet = getAttributeNameSet();
|
||||
private final AbstractSet<Entry<String, Object>> _entrySet = new AbstractSet<>()
|
||||
{
|
||||
@Override
|
||||
public Iterator<Entry<String, Object>> iterator()
|
||||
{
|
||||
Iterator<String> names = _attributeNameSet.iterator();
|
||||
return new Iterator<>()
|
||||
{
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return names.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entry<String, Object> 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<Entry<String, Object>> entrySet()
|
||||
{
|
||||
return new AbstractSet<>()
|
||||
{
|
||||
Iterator<String> names = getAttributeNameSet().iterator();
|
||||
|
||||
@Override
|
||||
public Iterator<Entry<String, Object>> iterator()
|
||||
{
|
||||
return new Iterator<>()
|
||||
{
|
||||
@Override
|
||||
public boolean hasNext()
|
||||
{
|
||||
return names.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entry<String, Object> 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;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue