From 6290fda4d3a794792dda75e0e4846a7c6c062a65 Mon Sep 17 00:00:00 2001 From: Sergey Rymsha Date: Thu, 10 Oct 2019 11:22:05 +0200 Subject: [PATCH] WebDispatcherImpl implementation issues #7523 keep elements with same order avoid copying on every dispatch --- .../web/impl/handler/WebDispatcherImpl.java | 21 ++++++++++++------- .../impl/handler/WebDispatcherImplTest.java | 14 +++++++++++++ 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/modules/web/web-impl/src/main/java/com/enonic/xp/web/impl/handler/WebDispatcherImpl.java b/modules/web/web-impl/src/main/java/com/enonic/xp/web/impl/handler/WebDispatcherImpl.java index 71ecb6ea80b..86e370d5afc 100644 --- a/modules/web/web-impl/src/main/java/com/enonic/xp/web/impl/handler/WebDispatcherImpl.java +++ b/modules/web/web-impl/src/main/java/com/enonic/xp/web/impl/handler/WebDispatcherImpl.java @@ -2,11 +2,14 @@ import java.util.Comparator; import java.util.Iterator; -import java.util.NavigableSet; -import java.util.concurrent.ConcurrentSkipListSet; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Predicate; +import java.util.stream.Stream; import org.osgi.service.component.annotations.Component; +import com.google.common.collect.ImmutableList; + import com.enonic.xp.web.WebRequest; import com.enonic.xp.web.WebResponse; import com.enonic.xp.web.handler.WebHandler; @@ -16,18 +19,22 @@ public final class WebDispatcherImpl implements WebDispatcher { - private final NavigableSet webHandlerList = new ConcurrentSkipListSet<>( Comparator.comparingInt( WebHandler::getOrder ) ); + private final AtomicReference> webHandlerListRef = new AtomicReference<>( ImmutableList.of() ); @Override public void add( final WebHandler webHandler ) { - this.webHandlerList.add( webHandler ); + webHandlerListRef.updateAndGet( oldWebHandlers -> Stream.concat( oldWebHandlers.stream(), Stream.of( webHandler ) ). + sorted( Comparator.comparingInt( WebHandler::getOrder ) ). + collect( ImmutableList.toImmutableList() ) ); } @Override public void remove( final WebHandler webHandler ) { - this.webHandlerList.remove( webHandler ); + webHandlerListRef.updateAndGet( oldWebHandlers -> oldWebHandlers.stream().filter( Predicate.not( w -> w != webHandler ) ). + sorted( Comparator.comparingInt( WebHandler::getOrder ) ). + collect( ImmutableList.toImmutableList() ) ); } @Override @@ -35,12 +42,12 @@ public WebResponse dispatch( final WebRequest req, final WebResponse res ) throws Exception { ServletRequestHolder.setRequest( req.getRawRequest() ); - return new WebHandlerChainImpl( this.webHandlerList ).handle( req, res ); + return new WebHandlerChainImpl( this.webHandlerListRef.get() ).handle( req, res ); } @Override public Iterator iterator() { - return this.webHandlerList.iterator(); + return this.webHandlerListRef.get().iterator(); } } diff --git a/modules/web/web-impl/src/test/java/com/enonic/xp/web/impl/handler/WebDispatcherImplTest.java b/modules/web/web-impl/src/test/java/com/enonic/xp/web/impl/handler/WebDispatcherImplTest.java index eb6617b2112..c33119130be 100644 --- a/modules/web/web-impl/src/test/java/com/enonic/xp/web/impl/handler/WebDispatcherImplTest.java +++ b/modules/web/web-impl/src/test/java/com/enonic/xp/web/impl/handler/WebDispatcherImplTest.java @@ -31,4 +31,18 @@ void orderedProperly() assertSame( webHandler1, list.get( 2 ) ); assertSame( webHandlerMax, list.get( 3 ) ); } + + @Test + void supportsEqualOderElements() + { + final WebDispatcherImpl dispatcher = new WebDispatcherImpl(); + TestWebHandler webHandler0 = new TestWebHandler( 0 ); + dispatcher.add( webHandler0 ); + TestWebHandler webHandlerAlso0 = new TestWebHandler( 0 ); + dispatcher.add( webHandlerAlso0 ); + + List list = StreamSupport.stream( dispatcher.spliterator(), false ).collect( Collectors.toList() ); + assertSame( webHandler0, list.get( 0 ) ); + assertSame( webHandlerAlso0, list.get( 1 ) ); + } }