Skip to content

Commit

Permalink
Issue #5020 Make servlets,filters,listeners beans again (#5028)
Browse files Browse the repository at this point in the history
* Issue #5020 Make servlets,filters,listeners beans again

Signed-off-by: Jan Bartel <[email protected]>
  • Loading branch information
janbartel authored Jul 14, 2020
1 parent ca404f1 commit b1e08ba
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ public ServletHandler()
{
}

@Override
public boolean isDumpable(Object o)
{
return !(o instanceof Holder || o instanceof BaseHolder || o instanceof FilterMapping || o instanceof ServletMapping);
}

@Override
public void dump(Appendable out, String indent) throws IOException
{
Expand Down Expand Up @@ -220,6 +226,13 @@ protected void start(LifeCycle l) throws Exception
if (!(l instanceof Holder))
super.start(l);
}

@Override
protected void stop(LifeCycle l) throws Exception
{
if (!(l instanceof Holder))
super.stop(l);
}

@Override
protected synchronized void doStop()
Expand Down Expand Up @@ -262,8 +275,10 @@ protected synchronized void doStop()

//Retain only filters and mappings that were added using jetty api (ie Source.EMBEDDED)
FilterHolder[] fhs = (FilterHolder[])LazyList.toArray(filterHolders, FilterHolder.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);
Expand Down Expand Up @@ -305,8 +320,10 @@ protected synchronized void doStop()

//Retain only Servlets and mappings added via jetty apis (ie Source.EMBEDDED)
ServletHolder[] shs = (ServletHolder[])LazyList.toArray(servletHolders, ServletHolder.class);
updateBeans(_servlets, shs);
_servlets = shs;
ServletMapping[] sms = (ServletMapping[])LazyList.toArray(servletMappings, ServletMapping.class);
updateBeans(_servletMappings, sms);
_servletMappings = sms;

if (_contextHandler != null)
Expand All @@ -331,6 +348,7 @@ protected synchronized void doStop()
}
}
ListenerHolder[] listeners = (ListenerHolder[])LazyList.toArray(listenerHolders, ListenerHolder.class);
updateBeans(_listeners, listeners);
_listeners = listeners;

//will be regenerated on next start
Expand Down Expand Up @@ -814,7 +832,7 @@ public void setListeners(ListenerHolder[] listeners)
{
holder.setServletHandler(this);
}

updateBeans(_listeners,listeners);
_listeners = listeners;
}

Expand Down Expand Up @@ -1516,6 +1534,7 @@ public void setFilterChainsCached(boolean filterChainsCached)
*/
public void setFilterMappings(FilterMapping[] filterMappings)
{
updateBeans(_filterMappings,filterMappings);
_filterMappings = filterMappings;
if (isStarted())
updateMappings();
Expand All @@ -1529,7 +1548,7 @@ public synchronized void setFilters(FilterHolder[] holders)
{
holder.setServletHandler(this);
}

updateBeans(_filters,holders);
_filters = holders;
updateNameMappings();
invalidateChainsCache();
Expand All @@ -1540,6 +1559,7 @@ public synchronized void setFilters(FilterHolder[] holders)
*/
public void setServletMappings(ServletMapping[] servletMappings)
{
updateBeans(_servletMappings,servletMappings);
_servletMappings = servletMappings;
if (isStarted())
updateMappings();
Expand All @@ -1558,7 +1578,7 @@ public synchronized void setServlets(ServletHolder[] holders)
{
holder.setServletHandler(this);
}

updateBeans(_servlets,holders);
_servlets = holders;
updateNameMappings();
invalidateChainsCache();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@

package org.eclipse.jetty.servlet;

import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import javax.servlet.DispatcherType;
import javax.servlet.http.HttpSessionEvent;
import javax.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.Test;

Expand Down Expand Up @@ -657,4 +662,72 @@ public void testAddFilterWithMappingAPI() throws Exception
assertTrue(fh3 == mappings[5].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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
* </pre>
*/
@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 = Log.getLogger(ContainerLifeCycle.class);
private final List<Bean> _beans = new CopyOnWriteArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,9 @@ else if (o instanceof Map)
static void dumpObjects(Appendable out, String indent, Object object, Object... extraChildren) throws IOException
{
dumpObject(out, object);

int extras = extraChildren == null ? 0 : extraChildren.length;

if (object instanceof Stream)
object = ((Stream)object).toArray();
if (object instanceof Array)
Expand Down Expand Up @@ -181,14 +181,18 @@ else if (object instanceof Map)
dumpObjects(out, nextIndent, item);
}
}

static void dumpContainer(Appendable out, String indent, Container object, boolean last) throws IOException
{
Container container = object;
ContainerLifeCycle containerLifeCycle = container instanceof ContainerLifeCycle ? (ContainerLifeCycle)container : null;
for (Iterator<Object> i = container.getBeans().iterator(); i.hasNext(); )
{
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) ? "| " : " ");
if (bean instanceof LifeCycle)
{
Expand Down Expand Up @@ -229,7 +233,7 @@ else if (containerLifeCycle != null && containerLifeCycle.isUnmanaged(bean))
}
}
}

static void dumpIterable(Appendable out, String indent, Iterable<?> iterable, boolean last) throws IOException
{
for (Iterator i = iterable.iterator(); i.hasNext(); )
Expand Down Expand Up @@ -267,4 +271,19 @@ static Dumpable named(String name, Object 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;
}
}
}

0 comments on commit b1e08ba

Please sign in to comment.