Mercurial Hosting > luan
diff src/org/eclipse/jetty/server/handler/ContextHandlerCollection.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | 8e9db0bbf4f9 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/org/eclipse/jetty/server/handler/ContextHandlerCollection.java Wed Sep 07 21:15:48 2016 -0600 @@ -0,0 +1,332 @@ +// +// ======================================================================== +// Copyright (c) 1995-2014 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 java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.eclipse.jetty.http.PathMap; +import org.eclipse.jetty.server.AsyncContinuation; +import org.eclipse.jetty.server.Handler; +import org.eclipse.jetty.server.HandlerContainer; +import org.eclipse.jetty.server.Request; +import org.eclipse.jetty.util.LazyList; +import org.eclipse.jetty.util.log.Log; +import org.eclipse.jetty.util.log.Logger; + +/* ------------------------------------------------------------ */ +/** ContextHandlerCollection. + * + * This {@link org.eclipse.jetty.server.handler.HandlerCollection} is creates a + * {@link org.eclipse.jetty.http.PathMap} to it's contained handlers based + * on the context path and virtual hosts of any contained {@link org.eclipse.jetty.server.handler.ContextHandler}s. + * The contexts do not need to be directly contained, only children of the contained handlers. + * Multiple contexts may have the same context path and they are called in order until one + * handles the request. + * + * @org.apache.xbean.XBean element="contexts" + */ +public class ContextHandlerCollection extends HandlerCollection +{ + private static final Logger LOG = Log.getLogger(ContextHandlerCollection.class); + + private volatile PathMap _contextMap; + private Class<? extends ContextHandler> _contextClass = ContextHandler.class; + + /* ------------------------------------------------------------ */ + public ContextHandlerCollection() + { + super(true); + } + + + /* ------------------------------------------------------------ */ + /** + * Remap the context paths. + */ + public void mapContexts() + { + PathMap contextMap = new PathMap(); + Handler[] branches = getHandlers(); + + + for (int b=0;branches!=null && b<branches.length;b++) + { + Handler[] handlers=null; + + if (branches[b] instanceof ContextHandler) + { + handlers = new Handler[]{ branches[b] }; + } + else if (branches[b] instanceof HandlerContainer) + { + handlers = ((HandlerContainer)branches[b]).getChildHandlersByClass(ContextHandler.class); + } + else + continue; + + for (int i=0;i<handlers.length;i++) + { + ContextHandler handler=(ContextHandler)handlers[i]; + + String contextPath=handler.getContextPath(); + + if (contextPath==null || contextPath.indexOf(',')>=0 || contextPath.startsWith("*")) + throw new IllegalArgumentException ("Illegal context spec:"+contextPath); + + if(!contextPath.startsWith("/")) + contextPath='/'+contextPath; + + if (contextPath.length()>1) + { + if (contextPath.endsWith("/")) + contextPath+="*"; + else if (!contextPath.endsWith("/*")) + contextPath+="/*"; + } + + Object contexts=contextMap.get(contextPath); + String[] vhosts=handler.getVirtualHosts(); + + + if (vhosts!=null && vhosts.length>0) + { + Map hosts; + + if (contexts instanceof Map) + hosts=(Map)contexts; + else + { + hosts=new HashMap(); + hosts.put("*",contexts); + contextMap.put(contextPath, hosts); + } + + for (int j=0;j<vhosts.length;j++) + { + String vhost=vhosts[j]; + contexts=hosts.get(vhost); + contexts=LazyList.add(contexts,branches[b]); + hosts.put(vhost,contexts); + } + } + else if (contexts instanceof Map) + { + Map hosts=(Map)contexts; + contexts=hosts.get("*"); + contexts= LazyList.add(contexts, branches[b]); + hosts.put("*",contexts); + } + else + { + contexts= LazyList.add(contexts, branches[b]); + contextMap.put(contextPath, contexts); + } + } + } + _contextMap=contextMap; + + } + + + + /* ------------------------------------------------------------ */ + /* + * @see org.eclipse.jetty.server.server.handler.HandlerCollection#setHandlers(org.eclipse.jetty.server.server.Handler[]) + */ + @Override + public void setHandlers(Handler[] handlers) + { + _contextMap=null; + super.setHandlers(handlers); + if (isStarted()) + mapContexts(); + } + + /* ------------------------------------------------------------ */ + @Override + protected void doStart() throws Exception + { + mapContexts(); + super.doStart(); + } + + + /* ------------------------------------------------------------ */ + /* + * @see org.eclipse.jetty.server.server.Handler#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int) + */ + @Override + public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException + { + Handler[] handlers = getHandlers(); + if (handlers==null || handlers.length==0) + return; + + AsyncContinuation async = baseRequest.getAsyncContinuation(); + if (async.isAsync()) + { + ContextHandler context=async.getContextHandler(); + if (context!=null) + { + context.handle(target,baseRequest,request, response); + return; + } + } + + // data structure which maps a request to a context; first-best match wins + // { context path => + // { virtual host => context } + // } + PathMap map = _contextMap; + if (map!=null && target!=null && target.startsWith("/")) + { + // first, get all contexts matched by context path + Object contexts = map.getLazyMatches(target); + + for (int i=0; i<LazyList.size(contexts); i++) + { + // then, match against the virtualhost of each context + Map.Entry entry = (Map.Entry)LazyList.get(contexts, i); + Object list = entry.getValue(); + + if (list instanceof Map) + { + Map hosts = (Map)list; + String host = normalizeHostname(request.getServerName()); + + // explicitly-defined virtual hosts, most specific + list=hosts.get(host); + for (int j=0; j<LazyList.size(list); j++) + { + Handler handler = (Handler)LazyList.get(list,j); + handler.handle(target,baseRequest, request, response); + if (baseRequest.isHandled()) + return; + } + + // wildcard for one level of names + list=hosts.get("*."+host.substring(host.indexOf(".")+1)); + for (int j=0; j<LazyList.size(list); j++) + { + Handler handler = (Handler)LazyList.get(list,j); + handler.handle(target,baseRequest, request, response); + if (baseRequest.isHandled()) + return; + } + + // no virtualhosts defined for the context, least specific + // will handle any request that does not match to a specific virtual host above + list=hosts.get("*"); + for (int j=0; j<LazyList.size(list); j++) + { + Handler handler = (Handler)LazyList.get(list,j); + handler.handle(target,baseRequest, request, response); + if (baseRequest.isHandled()) + return; + } + } + else + { + for (int j=0; j<LazyList.size(list); j++) + { + Handler handler = (Handler)LazyList.get(list,j); + handler.handle(target,baseRequest, request, response); + if (baseRequest.isHandled()) + return; + } + } + } + } + else + { + // This may not work in all circumstances... but then I think it should never be called + for (int i=0;i<handlers.length;i++) + { + handlers[i].handle(target,baseRequest, request, response); + if ( baseRequest.isHandled()) + return; + } + } + } + + + /* ------------------------------------------------------------ */ + /** Add a context handler. + * @param contextPath The context path to add + * @return the ContextHandler just added + */ + public ContextHandler addContext(String contextPath,String resourceBase) + { + try + { + ContextHandler context = _contextClass.newInstance(); + context.setContextPath(contextPath); + context.setResourceBase(resourceBase); + addHandler(context); + return context; + } + catch (Exception e) + { + LOG.debug(e); + throw new Error(e); + } + } + + + + /* ------------------------------------------------------------ */ + /** + * @return The class to use to add new Contexts + */ + public Class getContextClass() + { + return _contextClass; + } + + + /* ------------------------------------------------------------ */ + /** + * @param contextClass The class to use to add new Contexts + */ + public void setContextClass(Class contextClass) + { + if (contextClass ==null || !(ContextHandler.class.isAssignableFrom(contextClass))) + throw new IllegalArgumentException(); + _contextClass = contextClass; + } + + /* ------------------------------------------------------------ */ + private String normalizeHostname( String host ) + { + if ( host == null ) + return null; + + if ( host.endsWith( "." ) ) + return host.substring( 0, host.length() -1); + + return host; + } + +}