1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server.handler;
20
21 import java.io.IOException;
22
23 import javax.servlet.ServletException;
24 import javax.servlet.http.HttpServletRequest;
25 import javax.servlet.http.HttpServletResponse;
26
27 import org.eclipse.jetty.server.Handler;
28 import org.eclipse.jetty.server.HandlerContainer;
29 import org.eclipse.jetty.server.HttpChannelState;
30 import org.eclipse.jetty.server.Request;
31 import org.eclipse.jetty.util.ArrayTernaryTrie;
32 import org.eclipse.jetty.util.ArrayUtil;
33 import org.eclipse.jetty.util.Trie;
34 import org.eclipse.jetty.util.annotation.ManagedObject;
35 import org.eclipse.jetty.util.annotation.ManagedOperation;
36 import org.eclipse.jetty.util.log.Log;
37 import org.eclipse.jetty.util.log.Logger;
38
39
40
41
42
43
44
45
46
47
48
49
50 @ManagedObject("Context Handler Collection")
51 public class ContextHandlerCollection extends HandlerCollection
52 {
53 private static final Logger LOG = Log.getLogger(ContextHandlerCollection.class);
54
55 private volatile Trie<ContextHandler[]> _contexts;
56 private Class<? extends ContextHandler> _contextClass = ContextHandler.class;
57
58
59 public ContextHandlerCollection()
60 {
61 super(true);
62 }
63
64
65
66
67
68
69 @ManagedOperation("update the mapping of context path to context")
70 public void mapContexts()
71 {
72 int capacity=512;
73
74
75 Trie<ContextHandler[]> trie;
76 loop: while(true)
77 {
78 trie=new ArrayTernaryTrie<>(false,capacity);
79
80 Handler[] branches = getHandlers();
81
82
83 for (int b=0;branches!=null && b<branches.length;b++)
84 {
85 Handler[] handlers=null;
86
87 if (branches[b] instanceof ContextHandler)
88 {
89 handlers = new Handler[]{ branches[b] };
90 }
91 else if (branches[b] instanceof HandlerContainer)
92 {
93 handlers = ((HandlerContainer)branches[b]).getChildHandlersByClass(ContextHandler.class);
94 }
95 else
96 continue;
97
98
99 for (int i=0;handlers!=null && i<handlers.length;i++)
100 {
101 ContextHandler handler=(ContextHandler)handlers[i];
102 String contextPath=handler.getContextPath().substring(1);
103 ContextHandler[] contexts=trie.get(contextPath);
104
105 if (!trie.put(contextPath,ArrayUtil.addToArray(contexts,handler,ContextHandler.class)))
106 {
107 capacity+=512;
108 continue loop;
109 }
110 }
111 }
112
113 break;
114 }
115
116
117 for (String ctx : trie.keySet())
118 {
119 ContextHandler[] contexts=trie.get(ctx);
120 ContextHandler[] sorted=new ContextHandler[contexts.length];
121 int i=0;
122 for (ContextHandler handler:contexts)
123 if (handler.getVirtualHosts()!=null && handler.getVirtualHosts().length>0)
124 sorted[i++]=handler;
125 for (ContextHandler handler:contexts)
126 if (handler.getVirtualHosts()==null || handler.getVirtualHosts().length==0)
127 sorted[i++]=handler;
128 trie.put(ctx,sorted);
129 }
130
131
132
133 _contexts=trie;
134 }
135
136
137
138
139
140
141 @Override
142 public void setHandlers(Handler[] handlers)
143 {
144 super.setHandlers(handlers);
145 if (isStarted())
146 mapContexts();
147 }
148
149
150 @Override
151 protected void doStart() throws Exception
152 {
153 mapContexts();
154 super.doStart();
155 }
156
157
158
159
160
161
162 @Override
163 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
164 {
165 Handler[] handlers = getHandlers();
166 if (handlers==null || handlers.length==0)
167 return;
168
169 HttpChannelState async = baseRequest.getHttpChannelState();
170 if (async.isAsync())
171 {
172 ContextHandler context=async.getContextHandler();
173 if (context!=null)
174 {
175 context.handle(target,baseRequest,request, response);
176 return;
177 }
178 }
179
180
181
182
183 if (target.startsWith("/"))
184 {
185 int limit = target.length()-1;
186
187 while (limit>=0)
188 {
189
190 ContextHandler[] contexts = _contexts.getBest(target,1,limit);
191 if (contexts==null)
192 break;
193
194 int l=contexts[0].getContextPath().length();
195 if (l==1 || target.length()==l || target.charAt(l)=='/')
196 {
197 for (ContextHandler handler : contexts)
198 {
199 handler.handle(target,baseRequest, request, response);
200 if (baseRequest.isHandled())
201 return;
202 }
203 }
204
205 limit=l-2;
206 }
207 }
208 else
209 {
210
211 for (int i=0;i<handlers.length;i++)
212 {
213 handlers[i].handle(target,baseRequest, request, response);
214 if ( baseRequest.isHandled())
215 return;
216 }
217 }
218 }
219
220
221
222
223
224
225
226 public ContextHandler addContext(String contextPath,String resourceBase)
227 {
228 try
229 {
230 ContextHandler context = _contextClass.newInstance();
231 context.setContextPath(contextPath);
232 context.setResourceBase(resourceBase);
233 addHandler(context);
234 return context;
235 }
236 catch (Exception e)
237 {
238 LOG.debug(e);
239 throw new Error(e);
240 }
241 }
242
243
244
245
246
247
248
249 public Class<?> getContextClass()
250 {
251 return _contextClass;
252 }
253
254
255
256
257
258
259 public void setContextClass(Class<? extends ContextHandler> contextClass)
260 {
261 if (contextClass ==null || !(ContextHandler.class.isAssignableFrom(contextClass)))
262 throw new IllegalArgumentException();
263 _contextClass = contextClass;
264 }
265
266
267 }