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