diff options
18 files changed, 597 insertions, 231 deletions
diff --git a/jetty-distribution/src/main/resources/etc/jamon.xml b/jetty-distribution/src/main/resources/etc/jamon.xml index ec1d3f509b..2ec2d89db4 100644 --- a/jetty-distribution/src/main/resources/etc/jamon.xml +++ b/jetty-distribution/src/main/resources/etc/jamon.xml @@ -7,13 +7,13 @@ <Configure id="Server" class="org.eclipse.jetty.server.Server"> - <Get id="oldhandler" name="handler" /> - <Set name="handler"> - <New id="JamonHandler" class="com.jamonapi.http.JAMonJettyHandlerNew"> - <Set name="handler"><Ref refid="oldhandler" /></Set> - <Set name="summaryLabels"><Property name="jamon.summaryLabels" /></Set> - </New> - </Set> + <Call name="insertHandler"> + <Arg> + <New id="JamonHandler" class="com.jamonapi.http.JAMonJettyHandlerNew"> + <Set name="summaryLabels"><Property name="jamon.summaryLabels" /></Set> + </New> + </Arg> + </Call> <Ref refid="Contexts"> <Call name="addHandler"> diff --git a/jetty-rewrite/src/main/config/etc/jetty-rewrite.xml b/jetty-rewrite/src/main/config/etc/jetty-rewrite.xml index 65a5dea44a..0f37c7c5bb 100644 --- a/jetty-rewrite/src/main/config/etc/jetty-rewrite.xml +++ b/jetty-rewrite/src/main/config/etc/jetty-rewrite.xml @@ -1,47 +1,41 @@ <?xml version="1.0"?> <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd"> -<!-- =============================================================== --> -<!-- Mixin the RewriteHandler --> -<!-- =============================================================== --> - - <Configure id="Server" class="org.eclipse.jetty.server.Server"> <!-- =========================================================== --> <!-- configure rewrite handler --> <!-- =========================================================== --> - <Get id="oldhandler" name="handler"/> - - <Set name="handler"> - <New id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RewriteHandler"> - <Set name="handler"><Ref refid="oldhandler"/></Set> - <Set name="rewriteRequestURI"><Property name="jetty.rewrite.rewriteRequestURI" deprecated="rewrite.rewriteRequestURI" default="true"/></Set> - <Set name="rewritePathInfo"><Property name="jetty.rewrite.rewritePathInfo" deprecated="rewrite.rewritePathInfo" default="false"/></Set> - <Set name="originalPathAttribute"><Property name="jetty.rewrite.originalPathAttribute" deprecated="rewrite.originalPathAttribute" default="requestedPath"/></Set> - - <!-- Set DispatcherTypes --> - <Set name="dispatcherTypes"> - <Array type="javax.servlet.DispatcherType"> - <Item><Call class="javax.servlet.DispatcherType" name="valueOf"><Arg>REQUEST</Arg></Call></Item> - <Item><Call class="javax.servlet.DispatcherType" name="valueOf"><Arg>ASYNC</Arg></Call></Item> - </Array> - </Set> + <Call name="insertHandler"> + <Arg> + <New id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RewriteHandler"> + <Set name="rewriteRequestURI"><Property name="jetty.rewrite.rewriteRequestURI" deprecated="rewrite.rewriteRequestURI" default="true"/></Set> + <Set name="rewritePathInfo"><Property name="jetty.rewrite.rewritePathInfo" deprecated="rewrite.rewritePathInfo" default="false"/></Set> + <Set name="originalPathAttribute"><Property name="jetty.rewrite.originalPathAttribute" deprecated="rewrite.originalPathAttribute" default="requestedPath"/></Set> + + <!-- Set DispatcherTypes --> + <Set name="dispatcherTypes"> + <Array type="javax.servlet.DispatcherType"> + <Item><Call class="javax.servlet.DispatcherType" name="valueOf"><Arg>REQUEST</Arg></Call></Item> + <Item><Call class="javax.servlet.DispatcherType" name="valueOf"><Arg>ASYNC</Arg></Call></Item> + </Array> + </Set> - <!-- example rule --> - <!-- - <Call name="addRule"> - <Arg> - <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule"> - <Set name="pattern">/favicon.ico</Set> - <Set name="name">Cache-Control</Set> - <Set name="value">Max-Age=3600,public</Set> - <Set name="terminating">true</Set> - </New> - </Arg> - </Call> - --> + <!-- example rule --> + <!-- + <Call name="addRule"> + <Arg> + <New class="org.eclipse.jetty.rewrite.handler.HeaderPatternRule"> + <Set name="pattern">/favicon.ico</Set> + <Set name="name">Cache-Control</Set> + <Set name="value">Max-Age=3600,public</Set> + <Set name="terminating">true</Set> + </New> + </Arg> + </Call> + --> - </New> - </Set> + </New> + </Arg> + </Call> </Configure> diff --git a/jetty-server/src/main/config/etc/jetty-debuglog.xml b/jetty-server/src/main/config/etc/jetty-debuglog.xml index adbb10a5d4..0a082ce11f 100644 --- a/jetty-server/src/main/config/etc/jetty-debuglog.xml +++ b/jetty-server/src/main/config/etc/jetty-debuglog.xml @@ -6,20 +6,20 @@ <!-- =============================================================== --> <Configure id="Server" class="org.eclipse.jetty.server.Server"> - <Get id="oldhandler" name="handler"/> - <Set name="handler"> - <New id="DebugHandler" class="org.eclipse.jetty.server.handler.DebugHandler"> - <Set name="handler"><Ref refid="oldhandler"/></Set> - <Set name="outputStream"> - <New class="org.eclipse.jetty.util.RolloverFileOutputStream"> - <Arg type="String"><Property name="jetty.debuglog.dir" deprecated="jetty.logs" default="./logs"/>/yyyy_mm_dd.debug.log</Arg> - <Arg type="boolean"><Property name="jetty.debuglog.append" default="true"/></Arg> - <Arg type="int"><Property name="jetty.debuglog.retainDays" default="90"/></Arg> - <Arg> - <Call class="java.util.TimeZone" name="getTimeZone"><Arg><Property name="jetty.debuglog.timezone" default="GMT"/></Arg></Call> - </Arg> - </New> - </Set> - </New> - </Set> + <Call name="insertHandler"> + <Arg> + <New id="DebugHandler" class="org.eclipse.jetty.server.handler.DebugHandler"> + <Set name="outputStream"> + <New class="org.eclipse.jetty.util.RolloverFileOutputStream"> + <Arg type="String"><Property name="jetty.debuglog.dir" deprecated="jetty.logs" default="./logs"/>/yyyy_mm_dd.debug.log</Arg> + <Arg type="boolean"><Property name="jetty.debuglog.append" default="true"/></Arg> + <Arg type="int"><Property name="jetty.debuglog.retainDays" default="90"/></Arg> + <Arg> + <Call class="java.util.TimeZone" name="getTimeZone"><Arg><Property name="jetty.debuglog.timezone" default="GMT"/></Arg></Call> + </Arg> + </New> + </Set> + </New> + </Arg> + </Call> </Configure> diff --git a/jetty-server/src/main/config/etc/jetty-gzip.xml b/jetty-server/src/main/config/etc/jetty-gzip.xml index f26ef0b5a1..93b41fd639 100644 --- a/jetty-server/src/main/config/etc/jetty-gzip.xml +++ b/jetty-server/src/main/config/etc/jetty-gzip.xml @@ -9,59 +9,59 @@ <!-- =============================================================== --> <Configure id="Server" class="org.eclipse.jetty.server.Server"> - <Get id="next" name="handler" /> - <Set name="handler"> - <New id="GzipHandler" class="org.eclipse.jetty.server.handler.gzip.GzipHandler"> - <Set name="handler"><Ref refid="next" /></Set> - <Set name="minGzipSize"><Property name="jetty.gzip.minGzipSize" deprecated="gzip.minGzipSize" default="2048"/></Set> - <Set name="checkGzExists"><Property name="jetty.gzip.checkGzExists" deprecated="gzip.checkGzExists" default="false"/></Set> - <Set name="compressionLevel"><Property name="jetty.gzip.compressionLevel" deprecated="gzip.compressionLevel" default="-1"/></Set> - <Set name="excludedAgentPatterns"> - <Array type="String"> - <Item><Property name="jetty.gzip.excludedUserAgent" deprecated="gzip.excludedUserAgent" default=".*MSIE.6\.0.*"/></Item> - </Array> - </Set> + <Call name="insertHandler"> + <Arg> + <New id="GzipHandler" class="org.eclipse.jetty.server.handler.gzip.GzipHandler"> + <Set name="minGzipSize"><Property name="jetty.gzip.minGzipSize" deprecated="gzip.minGzipSize" default="2048"/></Set> + <Set name="checkGzExists"><Property name="jetty.gzip.checkGzExists" deprecated="gzip.checkGzExists" default="false"/></Set> + <Set name="compressionLevel"><Property name="jetty.gzip.compressionLevel" deprecated="gzip.compressionLevel" default="-1"/></Set> + <Set name="excludedAgentPatterns"> + <Array type="String"> + <Item><Property name="jetty.gzip.excludedUserAgent" deprecated="gzip.excludedUserAgent" default=".*MSIE.6\.0.*"/></Item> + </Array> + </Set> - <Set name="includedMethods"> - <Array type="String"> - <Item>GET</Item> - </Array> - </Set> + <Set name="includedMethods"> + <Array type="String"> + <Item>GET</Item> + </Array> + </Set> - <!-- - <Set name="includedPaths"> - <Array type="String"> - <Item>/*</Item> - </Array> - </Set> - --> + <!-- + <Set name="includedPaths"> + <Array type="String"> + <Item>/*</Item> + </Array> + </Set> + --> - <!-- - <Set name="excludedPaths"> - <Array type="String"> - <Item>*.gz</Item> - </Array> - </Set> - --> + <!-- + <Set name="excludedPaths"> + <Array type="String"> + <Item>*.gz</Item> + </Array> + </Set> + --> - <!-- - <Call name="addIncludedMimeTypes"> - <Arg><Array type="String"> - <Item>some/type</Item> - </Array></Arg> - </Call> - --> + <!-- + <Call name="addIncludedMimeTypes"> + <Arg><Array type="String"> + <Item>some/type</Item> + </Array></Arg> + </Call> + --> - <!-- - <Call name="addExcludedMimeTypes"> - <Arg><Array type="String"> - <Item>some/type</Item> - </Array></Arg> - </Call> - --> + <!-- + <Call name="addExcludedMimeTypes"> + <Arg><Array type="String"> + <Item>some/type</Item> + </Array></Arg> + </Call> + --> - </New> - </Set> + </New> + </Arg> + </Call> </Configure> diff --git a/jetty-server/src/main/config/etc/jetty-ipaccess.xml b/jetty-server/src/main/config/etc/jetty-ipaccess.xml index d8236a99a0..832565c5ad 100644 --- a/jetty-server/src/main/config/etc/jetty-ipaccess.xml +++ b/jetty-server/src/main/config/etc/jetty-ipaccess.xml @@ -6,26 +6,23 @@ <!-- =============================================================== --> <Configure id="Server" class="org.eclipse.jetty.server.Server"> - - <Get id="oldhandler" name="handler"/> - - <Set name="handler"> - <New id="IPAccessHandler" class="org.eclipse.jetty.server.handler.IPAccessHandler"> - <Set name="handler"><Ref refid="oldhandler"/></Set> - <Set name="white"> - <Array type="String"> - <Item>127.0.0.1</Item> - <Item>127.0.0.2/*.html</Item> - </Array> - </Set> - <Set name="black"> - <Array type="String"> - <Item>127.0.0.1/blacklisted</Item> - <Item>127.0.0.2/black.html</Item> - </Array> - </Set> - <Set name="whiteListByPath">false</Set> - </New> - </Set> - + <Call name="insertHandler"> + <Arg> + <New id="IPAccessHandler" class="org.eclipse.jetty.server.handler.IPAccessHandler"> + <Set name="white"> + <Array type="String"> + <Item>127.0.0.1</Item> + <Item>127.0.0.2/*.html</Item> + </Array> + </Set> + <Set name="black"> + <Array type="String"> + <Item>127.0.0.1/blacklisted</Item> + <Item>127.0.0.2/black.html</Item> + </Array> + </Set> + <Set name="whiteListByPath">false</Set> + </New> + </Arg> + </Call> </Configure> diff --git a/jetty-server/src/main/config/etc/jetty-stats.xml b/jetty-server/src/main/config/etc/jetty-stats.xml index 4e014906a5..445ae6a8a4 100644 --- a/jetty-server/src/main/config/etc/jetty-stats.xml +++ b/jetty-server/src/main/config/etc/jetty-stats.xml @@ -6,12 +6,12 @@ <!-- =============================================================== --> <Configure id="Server" class="org.eclipse.jetty.server.Server"> - <Get id="oldhandler" name="handler" /> - <Set name="handler"> - <New id="StatsHandler" class="org.eclipse.jetty.server.handler.StatisticsHandler"> - <Set name="handler"><Ref refid="oldhandler" /></Set> - </New> - </Set> + <Call name="insertHandler"> + <Arg> + <New id="StatsHandler" class="org.eclipse.jetty.server.handler.StatisticsHandler"> + </New> + </Arg> + </Call> <Call class="org.eclipse.jetty.server.ConnectorStatistics" name="addToAllConnectors"> <Arg><Ref refid="Server"/></Arg> </Call> diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java index 15429f88c6..745d56c9e6 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/ContextHandler.java @@ -100,7 +100,7 @@ import org.eclipse.jetty.util.resource.Resource; * The maximum size of a form that can be processed by this context is controlled by the system properties org.eclipse.jetty.server.Request.maxFormKeys * and org.eclipse.jetty.server.Request.maxFormContentSize. These can also be configured with {@link #setMaxFormContentSize(int)} and {@link #setMaxFormKeys(int)} * <p> - * This servers executore is made available via a context attributed "org.eclipse.jetty.server.Executor". + * This servers executor is made available via a context attributed "org.eclipse.jetty.server.Executor". * <p> * By default, the context is created with alias checkers for {@link AllowSymLinkAliasChecker} (unix only) and {@link ApproveNonExistentDirectoryAliases}. * If these alias checkers are not required, then {@link #clearAliasChecks()} or {@link #setAliasChecks(List)} should be called. diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java index e8ebe86dc5..ba5fae7d4f 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerCollection.java @@ -27,6 +27,7 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HandlerContainer; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.ArrayUtil; @@ -82,9 +83,18 @@ public class HandlerCollection extends AbstractHandlerContainer throw new IllegalStateException(STARTED); if (handlers!=null) + { + // check for loops + for (Handler handler:handlers) + if (handler == this || (handler instanceof HandlerContainer && + Arrays.asList(((HandlerContainer)handler).getChildHandlers()).contains(this))) + throw new IllegalStateException("setHandler loop"); + + // Set server for (Handler handler:handlers) if (handler.getServer()!=getServer()) handler.setServer(getServer()); + } Handler[] old=_handlers;; _handlers = handlers; updateBeans(old, handlers); diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java index f567f4ba80..e7e57c5556 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/handler/HandlerWrapper.java @@ -19,6 +19,7 @@ package org.eclipse.jetty.server.handler; import java.io.IOException; +import java.util.Arrays; import java.util.List; import javax.servlet.ServletException; @@ -27,6 +28,7 @@ import javax.servlet.http.HttpServletResponse; import org.eclipse.jetty.http.HttpStatus; import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HandlerContainer; import org.eclipse.jetty.server.Request; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.annotation.ManagedAttribute; @@ -82,6 +84,11 @@ public class HandlerWrapper extends AbstractHandlerContainer if (isStarted()) throw new IllegalStateException(STARTED); + // check for loops + if (handler==this || (handler instanceof HandlerContainer && + Arrays.asList(((HandlerContainer)handler).getChildHandlers()).contains(this))) + throw new IllegalStateException("setHandler loop"); + if (handler!=null) handler.setServer(getServer()); @@ -104,10 +111,18 @@ public class HandlerWrapper extends AbstractHandlerContainer */ public void insertHandler(HandlerWrapper wrapper) { - if (wrapper==null || wrapper.getHandler()!=null) + if (wrapper==null) throw new IllegalArgumentException(); - wrapper.setHandler(getHandler()); + + HandlerWrapper tail = wrapper; + while(tail.getHandler() instanceof HandlerWrapper) + tail=(HandlerWrapper)tail.getHandler(); + if (tail.getHandler()!=null) + throw new IllegalArgumentException("bad tail of inserted wrapper chain"); + + Handler next=getHandler(); setHandler(wrapper); + tail.setHandler(next); } /* ------------------------------------------------------------ */ diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/handler/HandlerTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/HandlerTest.java new file mode 100644 index 0000000000..c09e4037ba --- /dev/null +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/handler/HandlerTest.java @@ -0,0 +1,342 @@ +// +// ======================================================================== +// Copyright (c) 1995-2016 Mort Bay Consulting Pty. Ltd. +// ------------------------------------------------------------------------ +// All rights reserved. This program and the accompanying materials +// are made available under the terms of the Eclipse Public License v1.0 +// and Apache License v2.0 which accompanies this distribution. +// +// The Eclipse Public License is available at +// http://www.eclipse.org/legal/epl-v10.html +// +// The Apache License v2.0 is available at +// http://www.opensource.org/licenses/apache2.0.php +// +// You may elect to redistribute this code under either of these licenses. +// ======================================================================== +// + +package org.eclipse.jetty.server.handler; + +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.equalTo; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.*; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.server.handler.HandlerWrapper; +import org.hamcrest.Matchers; +import org.junit.Test; + +public class HandlerTest +{ + + @Test + public void testWrapperSetServer() + { + Server s=new Server(); + HandlerWrapper a = new HandlerWrapper(); + HandlerWrapper b = new HandlerWrapper(); + HandlerWrapper c = new HandlerWrapper(); + a.setHandler(b); + b.setHandler(c); + + a.setServer(s); + assertThat(b.getServer(),equalTo(s)); + assertThat(c.getServer(),equalTo(s)); + } + + @Test + public void testWrapperServerSet() + { + Server s=new Server(); + HandlerWrapper a = new HandlerWrapper(); + HandlerWrapper b = new HandlerWrapper(); + HandlerWrapper c = new HandlerWrapper(); + a.setServer(s); + b.setHandler(c); + a.setHandler(b); + + assertThat(b.getServer(),equalTo(s)); + assertThat(c.getServer(),equalTo(s)); + } + + @Test + public void testWrapperThisLoop() + { + HandlerWrapper a = new HandlerWrapper(); + + try + { + a.setHandler(a); + fail(); + } + catch(IllegalStateException e) + { + assertThat(e.getMessage(),containsString("loop")); + } + } + + @Test + public void testWrapperSimpleLoop() + { + HandlerWrapper a = new HandlerWrapper(); + HandlerWrapper b = new HandlerWrapper(); + + a.setHandler(b); + + try + { + b.setHandler(a); + fail(); + } + catch(IllegalStateException e) + { + assertThat(e.getMessage(),containsString("loop")); + } + } + + @Test + public void testWrapperDeepLoop() + { + HandlerWrapper a = new HandlerWrapper(); + HandlerWrapper b = new HandlerWrapper(); + HandlerWrapper c = new HandlerWrapper(); + + a.setHandler(b); + b.setHandler(c); + + try + { + c.setHandler(a); + fail(); + } + catch(IllegalStateException e) + { + assertThat(e.getMessage(),containsString("loop")); + } + } + + @Test + public void testWrapperChainLoop() + { + HandlerWrapper a = new HandlerWrapper(); + HandlerWrapper b = new HandlerWrapper(); + HandlerWrapper c = new HandlerWrapper(); + + a.setHandler(b); + c.setHandler(a); + + try + { + b.setHandler(c); + fail(); + } + catch(IllegalStateException e) + { + assertThat(e.getMessage(),containsString("loop")); + } + } + + + @Test + public void testCollectionSetServer() + { + Server s=new Server(); + HandlerCollection a = new HandlerCollection(); + HandlerCollection b = new HandlerCollection(); + HandlerCollection b1 = new HandlerCollection(); + HandlerCollection b2 = new HandlerCollection(); + HandlerCollection c = new HandlerCollection(); + HandlerCollection c1 = new HandlerCollection(); + HandlerCollection c2 = new HandlerCollection(); + + a.addHandler(b); + a.addHandler(c); + b.setHandlers(new Handler[]{b1,b2}); + c.setHandlers(new Handler[]{c1,c2}); + a.setServer(s); + + assertThat(b.getServer(),equalTo(s)); + assertThat(c.getServer(),equalTo(s)); + assertThat(b1.getServer(),equalTo(s)); + assertThat(b2.getServer(),equalTo(s)); + assertThat(c1.getServer(),equalTo(s)); + assertThat(c2.getServer(),equalTo(s)); + } + + @Test + public void testCollectionServerSet() + { + Server s=new Server(); + HandlerCollection a = new HandlerCollection(); + HandlerCollection b = new HandlerCollection(); + HandlerCollection b1 = new HandlerCollection(); + HandlerCollection b2 = new HandlerCollection(); + HandlerCollection c = new HandlerCollection(); + HandlerCollection c1 = new HandlerCollection(); + HandlerCollection c2 = new HandlerCollection(); + + a.setServer(s); + a.addHandler(b); + a.addHandler(c); + b.setHandlers(new Handler[]{b1,b2}); + c.setHandlers(new Handler[]{c1,c2}); + + assertThat(b.getServer(),equalTo(s)); + assertThat(c.getServer(),equalTo(s)); + assertThat(b1.getServer(),equalTo(s)); + assertThat(b2.getServer(),equalTo(s)); + assertThat(c1.getServer(),equalTo(s)); + assertThat(c2.getServer(),equalTo(s)); + } + + @Test + public void testCollectionThisLoop() + { + HandlerCollection a = new HandlerCollection(); + + try + { + a.addHandler(a); + fail(); + } + catch(IllegalStateException e) + { + assertThat(e.getMessage(),containsString("loop")); + } + } + + @Test + public void testCollectionDeepLoop() + { + HandlerCollection a = new HandlerCollection(); + HandlerCollection b = new HandlerCollection(); + HandlerCollection b1 = new HandlerCollection(); + HandlerCollection b2 = new HandlerCollection(); + HandlerCollection c = new HandlerCollection(); + HandlerCollection c1 = new HandlerCollection(); + HandlerCollection c2 = new HandlerCollection(); + + a.addHandler(b); + a.addHandler(c); + b.setHandlers(new Handler[]{b1,b2}); + c.setHandlers(new Handler[]{c1,c2}); + + try + { + b2.addHandler(a); + fail(); + } + catch(IllegalStateException e) + { + assertThat(e.getMessage(),containsString("loop")); + } + } + + @Test + public void testCollectionChainLoop() + { + HandlerCollection a = new HandlerCollection(); + HandlerCollection b = new HandlerCollection(); + HandlerCollection b1 = new HandlerCollection(); + HandlerCollection b2 = new HandlerCollection(); + HandlerCollection c = new HandlerCollection(); + HandlerCollection c1 = new HandlerCollection(); + HandlerCollection c2 = new HandlerCollection(); + + a.addHandler(c); + b.setHandlers(new Handler[]{b1,b2}); + c.setHandlers(new Handler[]{c1,c2}); + b2.addHandler(a); + + try + { + a.addHandler(b); + fail(); + } + catch(IllegalStateException e) + { + assertThat(e.getMessage(),containsString("loop")); + } + } + + @Test + public void testInsertWrapperTail() + { + HandlerWrapper a = new HandlerWrapper(); + HandlerWrapper b = new HandlerWrapper(); + + a.insertHandler(b); + assertThat(a.getHandler(),equalTo(b)); + assertThat(b.getHandler(),nullValue()); + } + + @Test + public void testInsertWrapper() + { + HandlerWrapper a = new HandlerWrapper(); + HandlerWrapper b = new HandlerWrapper(); + HandlerWrapper c = new HandlerWrapper(); + + a.insertHandler(c); + a.insertHandler(b); + assertThat(a.getHandler(),equalTo(b)); + assertThat(b.getHandler(),equalTo(c)); + assertThat(c.getHandler(),nullValue()); + } + + @Test + public void testInsertWrapperChain() + { + HandlerWrapper a = new HandlerWrapper(); + HandlerWrapper b = new HandlerWrapper(); + HandlerWrapper c = new HandlerWrapper(); + HandlerWrapper d = new HandlerWrapper(); + + a.insertHandler(d); + b.insertHandler(c); + a.insertHandler(b); + assertThat(a.getHandler(),equalTo(b)); + assertThat(b.getHandler(),equalTo(c)); + assertThat(c.getHandler(),equalTo(d)); + assertThat(d.getHandler(),nullValue()); + } + + @Test + public void testInsertWrapperBadChain() + { + HandlerWrapper a = new HandlerWrapper(); + HandlerWrapper b = new HandlerWrapper(); + HandlerWrapper c = new HandlerWrapper(); + HandlerWrapper d = new HandlerWrapper(); + + a.insertHandler(d); + b.insertHandler(c); + c.setHandler(new AbstractHandler() + { + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + { + } + }); + + try + { + a.insertHandler(b); + fail(); + } + catch(IllegalArgumentException e) + { + assertThat(e.getMessage(),containsString("bad tail")); + } + } +} diff --git a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java index c5ffbd382c..3b23ec4f3d 100644 --- a/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java +++ b/jetty-servlet/src/main/java/org/eclipse/jetty/servlet/ServletContextHandler.java @@ -66,6 +66,8 @@ import org.eclipse.jetty.util.DeprecationWarning; import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedObject; import org.eclipse.jetty.util.component.LifeCycle; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; /** * Servlet Context. @@ -83,6 +85,8 @@ import org.eclipse.jetty.util.component.LifeCycle; @ManagedObject("Servlet Context Handler") public class ServletContextHandler extends ContextHandler { + private static final Logger LOG = Log.getLogger(ServletContextHandler.class); + public final static int SESSIONS=1; public final static int SECURITY=2; public final static int GZIP=4; @@ -169,7 +173,21 @@ public class ServletContextHandler extends ContextHandler if (errorHandler!=null) setErrorHandler(errorHandler); + } + + @Override + public void setHandler(Handler handler) + { + LOG.warn("ServletContextHandler.setHandler should not be called directly. Use insertHandler or setSessionHandler etc."); + super.setHandler(handler); + } + private void doSetHandler(HandlerWrapper wrapper, Handler handler) + { + if (wrapper==this) + super.setHandler(handler); + else + wrapper.setHandler(handler); } /* ------------------------------------------------------------ */ @@ -189,12 +207,7 @@ public class ServletContextHandler extends ContextHandler handler=(HandlerWrapper)handler.getHandler(); if (handler.getHandler()!=_sessionHandler) - { - if (handler== this) - super.setHandler(_sessionHandler); - else - handler.setHandler(_sessionHandler); - } + doSetHandler(handler,_sessionHandler); handler=_sessionHandler; } @@ -208,12 +221,7 @@ public class ServletContextHandler extends ContextHandler handler=(HandlerWrapper)handler.getHandler(); if (handler.getHandler()!=_securityHandler) - { - if (handler== this) - super.setHandler(_securityHandler); - else - handler.setHandler(_securityHandler); - } + doSetHandler(handler,_securityHandler); handler=_securityHandler; } @@ -226,12 +234,7 @@ public class ServletContextHandler extends ContextHandler handler=(HandlerWrapper)handler.getHandler(); if (handler.getHandler()!=_gzipHandler) - { - if (handler== this) - super.setHandler(_gzipHandler); - else - handler.setHandler(_gzipHandler); - } + doSetHandler(handler,_gzipHandler); handler=_gzipHandler; } @@ -244,12 +247,7 @@ public class ServletContextHandler extends ContextHandler handler=(HandlerWrapper)handler.getHandler(); if (handler.getHandler()!=_servletHandler) - { - if (handler== this) - super.setHandler(_servletHandler); - else - handler.setHandler(_servletHandler); - } + doSetHandler(handler,_servletHandler); handler=_servletHandler; } @@ -554,7 +552,7 @@ public class ServletContextHandler extends ContextHandler { if (wrapper.getHandler()==handler) { - wrapper.setHandler(replace); + doSetHandler(wrapper,replace); return true; } @@ -664,20 +662,38 @@ public class ServletContextHandler extends ContextHandler */ public void insertHandler(HandlerWrapper handler) { - HandlerWrapper h=this; - - // Skip any injected handlers - while (h.getHandler() instanceof HandlerWrapper) - { - HandlerWrapper wrapper = (HandlerWrapper)h.getHandler(); - if (wrapper instanceof SessionHandler || - wrapper instanceof SecurityHandler || - wrapper instanceof ServletHandler) - break; - h=wrapper; + if (handler instanceof SessionHandler) + setSessionHandler((SessionHandler)handler); + else if (handler instanceof SecurityHandler) + setSecurityHandler((SecurityHandler)handler); + else if (handler instanceof GzipHandler) + setGzipHandler((GzipHandler)handler); + else if (handler instanceof ServletHandler) + setServletHandler((ServletHandler)handler); + else + { + HandlerWrapper tail = handler; + while(tail.getHandler() instanceof HandlerWrapper) + tail=(HandlerWrapper)tail.getHandler(); + if (tail.getHandler()!=null) + throw new IllegalArgumentException("bad tail of inserted wrapper chain"); + + // Skip any injected handlers + HandlerWrapper h=this; + while (h.getHandler() instanceof HandlerWrapper) + { + HandlerWrapper wrapper = (HandlerWrapper)h.getHandler(); + if (wrapper instanceof SessionHandler || + wrapper instanceof SecurityHandler || + wrapper instanceof ServletHandler) + break; + h=wrapper; + } + + Handler next=h.getHandler(); + doSetHandler(h,handler); + doSetHandler(tail,next); } - - h.setHandler(handler); relinkHandlers(); } diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java index 4be7ff073c..99ca52f754 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/GzipHandlerTest.java @@ -81,7 +81,6 @@ public class GzipHandlerTest _server.setHandler(gzipHandler); gzipHandler.setHandler(context); - context.setHandler(servlets); servlets.addServletWithMapping(TestServlet.class,"/content"); servlets.addServletWithMapping(ForwardServlet.class,"/forward"); servlets.addServletWithMapping(IncludeServlet.class,"/include"); @@ -91,7 +90,6 @@ public class GzipHandlerTest public static class TestServlet extends HttpServlet { - @Override protected void doGet(HttpServletRequest req, HttpServletResponse response) throws ServletException, IOException { diff --git a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java index f088ffd3fc..2b2c671f96 100644 --- a/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java +++ b/jetty-servlet/src/test/java/org/eclipse/jetty/servlet/ServletHandlerTest.java @@ -26,6 +26,7 @@ import java.util.EnumSet; import javax.servlet.DispatcherType; +import org.eclipse.jetty.server.handler.HandlerWrapper; import org.eclipse.jetty.servlet.BaseHolder.Source; import org.junit.Before; import org.junit.Test; @@ -428,5 +429,4 @@ public class ServletHandlerTest } - } diff --git a/jetty-servlets/src/test/java/org/eclipse/jetty/server/handler/gzip/IncludedGzipTest.java b/jetty-servlets/src/test/java/org/eclipse/jetty/server/handler/gzip/IncludedGzipTest.java index 4e02fccbb8..bea2501e8b 100644 --- a/jetty-servlets/src/test/java/org/eclipse/jetty/server/handler/gzip/IncludedGzipTest.java +++ b/jetty-servlets/src/test/java/org/eclipse/jetty/server/handler/gzip/IncludedGzipTest.java @@ -89,8 +89,7 @@ public class IncludedGzipTest tester.getContext().addServlet(org.eclipse.jetty.servlet.DefaultServlet.class, "/"); GzipHandler gzipHandler = new GzipHandler(); - gzipHandler.setHandler(tester.getContext().getHandler()); - tester.getContext().setHandler(gzipHandler); + tester.getContext().insertHandler(gzipHandler); tester.start(); } diff --git a/tests/test-integration/src/test/resources/DefaultHandler.xml b/tests/test-integration/src/test/resources/DefaultHandler.xml index a0504083bf..7920979deb 100644 --- a/tests/test-integration/src/test/resources/DefaultHandler.xml +++ b/tests/test-integration/src/test/resources/DefaultHandler.xml @@ -41,8 +41,8 @@ <New id="defcontext" class="org.eclipse.jetty.server.handler.ContextHandler"> <Set name="contextPath">/tests</Set> <Set name="ResourceBase"><Property name="test.docroot.base"/>/default</Set> - <Set name="Handler"><New id="reshandler" class="org.eclipse.jetty.server.handler.ResourceHandler"/></Set> - <Set name="DisplayName">default</Set> + <Set name="Handler"><New id="reshandler" class="org.eclipse.jetty.server.handler.ResourceHandler"/></Set> + <Set name="DisplayName">default</Set> </New> </Item> </Array> diff --git a/tests/test-integration/src/test/resources/RFC2616Base.xml b/tests/test-integration/src/test/resources/RFC2616Base.xml index a35088f5e8..9a1d4ae094 100644 --- a/tests/test-integration/src/test/resources/RFC2616Base.xml +++ b/tests/test-integration/src/test/resources/RFC2616Base.xml @@ -102,12 +102,10 @@ </Arg> </Call> - - - <!-- =========================================================== --> - <!-- extra options --> - <!-- =========================================================== --> - <Set name="stopAtShutdown">true</Set> - <Set name="stopTimeout">1000</Set> + <!-- =========================================================== --> + <!-- extra options --> + <!-- =========================================================== --> + <Set name="stopAtShutdown">true</Set> + <Set name="stopTimeout">1000</Set> </Configure> diff --git a/tests/test-integration/src/test/resources/RFC2616_Redirects.xml b/tests/test-integration/src/test/resources/RFC2616_Redirects.xml index a777ad1e89..fca59dd34b 100644 --- a/tests/test-integration/src/test/resources/RFC2616_Redirects.xml +++ b/tests/test-integration/src/test/resources/RFC2616_Redirects.xml @@ -2,53 +2,51 @@ <!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure_9_3.dtd"> <Configure id="Server" class="org.eclipse.jetty.server.Server"> - <!-- =========================================================== --> - <!-- Configure Rewrite Handler --> - <!-- =========================================================== --> - <Get id="oldhandler" name="handler"/> + <!-- =========================================================== --> + <!-- Configure Rewrite Handler --> + <!-- =========================================================== --> - <Set name="handler"> + <Call name="insertHandler"> + <Arg> <New id="Rewrite" class="org.eclipse.jetty.rewrite.handler.RewriteHandler"> - - <Set name="handler"><Ref refid="oldhandler"/></Set> <Set name="rewriteRequestURI">true</Set> <Set name="rewritePathInfo">false</Set> <Set name="originalPathAttribute">requestedPath</Set> <Set name="rules"> - <Array type="org.eclipse.jetty.rewrite.handler.Rule"> - - <!-- add a response rule --> - <!-- - <Item> - <New id="response" class="org.eclipse.jetty.rewrite.handler.ResponsePatternRule"> - <Set name="pattern">/rewrite/session/</Set> - <Set name="code">401</Set> - <Set name="reason">Setting error code 401</Set> - </New> - </Item> - --> - - <!-- add a simple redirect --> - <!-- - <Item> - <New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectPatternRule"> - <Set name="pattern">/redirect/*</Set> - <Set name="location">/tests/</Set> - </New> - </Item> - --> - - <!-- add a regex rewrite redirect --> - <Item> - <New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectRegexRule"> - <Set name="regex">/redirect/(.*)</Set> - <Set name="replacement">/tests/$1</Set> - </New> - </Item> - </Array> - </Set> + <Array type="org.eclipse.jetty.rewrite.handler.Rule"> + + <!-- add a response rule --> + <!-- + <Item> + <New id="response" class="org.eclipse.jetty.rewrite.handler.ResponsePatternRule"> + <Set name="pattern">/rewrite/session/</Set> + <Set name="code">401</Set> + <Set name="reason">Setting error code 401</Set> + </New> + </Item> + --> + + <!-- add a simple redirect --> + <!-- + <Item> + <New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectPatternRule"> + <Set name="pattern">/redirect/*</Set> + <Set name="location">/tests/</Set> + </New> + </Item> + --> + + <!-- add a regex rewrite redirect --> + <Item> + <New id="redirect" class="org.eclipse.jetty.rewrite.handler.RedirectRegexRule"> + <Set name="regex">/redirect/(.*)</Set> + <Set name="replacement">/tests/$1</Set> + </New> + </Item> + </Array> + </Set> </New> - </Set> - + </Arg> + </Call> </Configure> diff --git a/tests/test-webapps/test-jetty-webapp/src/main/assembly/embedded-jetty-web-for-webbundle.xml b/tests/test-webapps/test-jetty-webapp/src/main/assembly/embedded-jetty-web-for-webbundle.xml index 9b4e89280b..0d750b5cdd 100644 --- a/tests/test-webapps/test-jetty-webapp/src/main/assembly/embedded-jetty-web-for-webbundle.xml +++ b/tests/test-webapps/test-jetty-webapp/src/main/assembly/embedded-jetty-web-for-webbundle.xml @@ -13,7 +13,6 @@ detected. <Configure class="org.eclipse.jetty.webapp.WebAppContext"> - <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> <!-- Required minimal context configuration : --> <!-- + contextPath --> |