comparison 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
comparison
equal deleted inserted replaced
801:6a21393191c1 802:3428c60d7cfc
1 //
2 // ========================================================================
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
8 //
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
11 //
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
14 //
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
17 //
18
19 package org.eclipse.jetty.server.handler;
20
21 import java.io.IOException;
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import javax.servlet.ServletException;
26 import javax.servlet.http.HttpServletRequest;
27 import javax.servlet.http.HttpServletResponse;
28
29 import org.eclipse.jetty.http.PathMap;
30 import org.eclipse.jetty.server.AsyncContinuation;
31 import org.eclipse.jetty.server.Handler;
32 import org.eclipse.jetty.server.HandlerContainer;
33 import org.eclipse.jetty.server.Request;
34 import org.eclipse.jetty.util.LazyList;
35 import org.eclipse.jetty.util.log.Log;
36 import org.eclipse.jetty.util.log.Logger;
37
38 /* ------------------------------------------------------------ */
39 /** ContextHandlerCollection.
40 *
41 * This {@link org.eclipse.jetty.server.handler.HandlerCollection} is creates a
42 * {@link org.eclipse.jetty.http.PathMap} to it's contained handlers based
43 * on the context path and virtual hosts of any contained {@link org.eclipse.jetty.server.handler.ContextHandler}s.
44 * The contexts do not need to be directly contained, only children of the contained handlers.
45 * Multiple contexts may have the same context path and they are called in order until one
46 * handles the request.
47 *
48 * @org.apache.xbean.XBean element="contexts"
49 */
50 public class ContextHandlerCollection extends HandlerCollection
51 {
52 private static final Logger LOG = Log.getLogger(ContextHandlerCollection.class);
53
54 private volatile PathMap _contextMap;
55 private Class<? extends ContextHandler> _contextClass = ContextHandler.class;
56
57 /* ------------------------------------------------------------ */
58 public ContextHandlerCollection()
59 {
60 super(true);
61 }
62
63
64 /* ------------------------------------------------------------ */
65 /**
66 * Remap the context paths.
67 */
68 public void mapContexts()
69 {
70 PathMap contextMap = new PathMap();
71 Handler[] branches = getHandlers();
72
73
74 for (int b=0;branches!=null && b<branches.length;b++)
75 {
76 Handler[] handlers=null;
77
78 if (branches[b] instanceof ContextHandler)
79 {
80 handlers = new Handler[]{ branches[b] };
81 }
82 else if (branches[b] instanceof HandlerContainer)
83 {
84 handlers = ((HandlerContainer)branches[b]).getChildHandlersByClass(ContextHandler.class);
85 }
86 else
87 continue;
88
89 for (int i=0;i<handlers.length;i++)
90 {
91 ContextHandler handler=(ContextHandler)handlers[i];
92
93 String contextPath=handler.getContextPath();
94
95 if (contextPath==null || contextPath.indexOf(',')>=0 || contextPath.startsWith("*"))
96 throw new IllegalArgumentException ("Illegal context spec:"+contextPath);
97
98 if(!contextPath.startsWith("/"))
99 contextPath='/'+contextPath;
100
101 if (contextPath.length()>1)
102 {
103 if (contextPath.endsWith("/"))
104 contextPath+="*";
105 else if (!contextPath.endsWith("/*"))
106 contextPath+="/*";
107 }
108
109 Object contexts=contextMap.get(contextPath);
110 String[] vhosts=handler.getVirtualHosts();
111
112
113 if (vhosts!=null && vhosts.length>0)
114 {
115 Map hosts;
116
117 if (contexts instanceof Map)
118 hosts=(Map)contexts;
119 else
120 {
121 hosts=new HashMap();
122 hosts.put("*",contexts);
123 contextMap.put(contextPath, hosts);
124 }
125
126 for (int j=0;j<vhosts.length;j++)
127 {
128 String vhost=vhosts[j];
129 contexts=hosts.get(vhost);
130 contexts=LazyList.add(contexts,branches[b]);
131 hosts.put(vhost,contexts);
132 }
133 }
134 else if (contexts instanceof Map)
135 {
136 Map hosts=(Map)contexts;
137 contexts=hosts.get("*");
138 contexts= LazyList.add(contexts, branches[b]);
139 hosts.put("*",contexts);
140 }
141 else
142 {
143 contexts= LazyList.add(contexts, branches[b]);
144 contextMap.put(contextPath, contexts);
145 }
146 }
147 }
148 _contextMap=contextMap;
149
150 }
151
152
153
154 /* ------------------------------------------------------------ */
155 /*
156 * @see org.eclipse.jetty.server.server.handler.HandlerCollection#setHandlers(org.eclipse.jetty.server.server.Handler[])
157 */
158 @Override
159 public void setHandlers(Handler[] handlers)
160 {
161 _contextMap=null;
162 super.setHandlers(handlers);
163 if (isStarted())
164 mapContexts();
165 }
166
167 /* ------------------------------------------------------------ */
168 @Override
169 protected void doStart() throws Exception
170 {
171 mapContexts();
172 super.doStart();
173 }
174
175
176 /* ------------------------------------------------------------ */
177 /*
178 * @see org.eclipse.jetty.server.server.Handler#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
179 */
180 @Override
181 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
182 {
183 Handler[] handlers = getHandlers();
184 if (handlers==null || handlers.length==0)
185 return;
186
187 AsyncContinuation async = baseRequest.getAsyncContinuation();
188 if (async.isAsync())
189 {
190 ContextHandler context=async.getContextHandler();
191 if (context!=null)
192 {
193 context.handle(target,baseRequest,request, response);
194 return;
195 }
196 }
197
198 // data structure which maps a request to a context; first-best match wins
199 // { context path =>
200 // { virtual host => context }
201 // }
202 PathMap map = _contextMap;
203 if (map!=null && target!=null && target.startsWith("/"))
204 {
205 // first, get all contexts matched by context path
206 Object contexts = map.getLazyMatches(target);
207
208 for (int i=0; i<LazyList.size(contexts); i++)
209 {
210 // then, match against the virtualhost of each context
211 Map.Entry entry = (Map.Entry)LazyList.get(contexts, i);
212 Object list = entry.getValue();
213
214 if (list instanceof Map)
215 {
216 Map hosts = (Map)list;
217 String host = normalizeHostname(request.getServerName());
218
219 // explicitly-defined virtual hosts, most specific
220 list=hosts.get(host);
221 for (int j=0; j<LazyList.size(list); j++)
222 {
223 Handler handler = (Handler)LazyList.get(list,j);
224 handler.handle(target,baseRequest, request, response);
225 if (baseRequest.isHandled())
226 return;
227 }
228
229 // wildcard for one level of names
230 list=hosts.get("*."+host.substring(host.indexOf(".")+1));
231 for (int j=0; j<LazyList.size(list); j++)
232 {
233 Handler handler = (Handler)LazyList.get(list,j);
234 handler.handle(target,baseRequest, request, response);
235 if (baseRequest.isHandled())
236 return;
237 }
238
239 // no virtualhosts defined for the context, least specific
240 // will handle any request that does not match to a specific virtual host above
241 list=hosts.get("*");
242 for (int j=0; j<LazyList.size(list); j++)
243 {
244 Handler handler = (Handler)LazyList.get(list,j);
245 handler.handle(target,baseRequest, request, response);
246 if (baseRequest.isHandled())
247 return;
248 }
249 }
250 else
251 {
252 for (int j=0; j<LazyList.size(list); j++)
253 {
254 Handler handler = (Handler)LazyList.get(list,j);
255 handler.handle(target,baseRequest, request, response);
256 if (baseRequest.isHandled())
257 return;
258 }
259 }
260 }
261 }
262 else
263 {
264 // This may not work in all circumstances... but then I think it should never be called
265 for (int i=0;i<handlers.length;i++)
266 {
267 handlers[i].handle(target,baseRequest, request, response);
268 if ( baseRequest.isHandled())
269 return;
270 }
271 }
272 }
273
274
275 /* ------------------------------------------------------------ */
276 /** Add a context handler.
277 * @param contextPath The context path to add
278 * @return the ContextHandler just added
279 */
280 public ContextHandler addContext(String contextPath,String resourceBase)
281 {
282 try
283 {
284 ContextHandler context = _contextClass.newInstance();
285 context.setContextPath(contextPath);
286 context.setResourceBase(resourceBase);
287 addHandler(context);
288 return context;
289 }
290 catch (Exception e)
291 {
292 LOG.debug(e);
293 throw new Error(e);
294 }
295 }
296
297
298
299 /* ------------------------------------------------------------ */
300 /**
301 * @return The class to use to add new Contexts
302 */
303 public Class getContextClass()
304 {
305 return _contextClass;
306 }
307
308
309 /* ------------------------------------------------------------ */
310 /**
311 * @param contextClass The class to use to add new Contexts
312 */
313 public void setContextClass(Class contextClass)
314 {
315 if (contextClass ==null || !(ContextHandler.class.isAssignableFrom(contextClass)))
316 throw new IllegalArgumentException();
317 _contextClass = contextClass;
318 }
319
320 /* ------------------------------------------------------------ */
321 private String normalizeHostname( String host )
322 {
323 if ( host == null )
324 return null;
325
326 if ( host.endsWith( "." ) )
327 return host.substring( 0, host.length() -1);
328
329 return host;
330 }
331
332 }