1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server;
15
16 import java.io.IOException;
17 import java.lang.reflect.Method;
18 import java.util.ArrayList;
19 import java.util.Enumeration;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.ListIterator;
23 import java.util.Set;
24 import java.util.concurrent.CopyOnWriteArraySet;
25
26 import javax.servlet.ServletException;
27 import javax.servlet.http.HttpServletRequest;
28 import javax.servlet.http.HttpServletResponse;
29
30 import org.eclipse.jetty.http.HttpGenerator;
31 import org.eclipse.jetty.http.HttpURI;
32 import org.eclipse.jetty.server.bio.SocketConnector;
33 import org.eclipse.jetty.server.handler.HandlerWrapper;
34 import org.eclipse.jetty.server.nio.SelectChannelConnector;
35 import org.eclipse.jetty.util.Attributes;
36 import org.eclipse.jetty.util.AttributesMap;
37 import org.eclipse.jetty.util.LazyList;
38 import org.eclipse.jetty.util.MultiException;
39 import org.eclipse.jetty.util.URIUtil;
40 import org.eclipse.jetty.util.component.Container;
41 import org.eclipse.jetty.util.component.LifeCycle;
42 import org.eclipse.jetty.util.log.Log;
43 import org.eclipse.jetty.util.thread.QueuedThreadPool;
44 import org.eclipse.jetty.util.thread.ShutdownThread;
45 import org.eclipse.jetty.util.thread.ThreadPool;
46
47
48
49
50
51
52
53
54
55
56 public class Server extends HandlerWrapper implements Attributes
57 {
58 private static final String _version;
59 static
60 {
61 if (Server.class.getPackage()!=null && Server.class.getPackage().getImplementationVersion()!=null)
62 _version=Server.class.getPackage().getImplementationVersion();
63 else
64 _version=System.getProperty("jetty.version","7.0.2-SNAPSHOT");
65 }
66 private final Container _container=new Container();
67 private final AttributesMap _attributes = new AttributesMap();
68 private final List<Object> _dependentBeans=new ArrayList<Object>();
69 private ThreadPool _threadPool;
70 private Connector[] _connectors;
71 private SessionIdManager _sessionIdManager;
72 private boolean _sendServerVersion = true;
73 private boolean _sendDateHeader = false;
74 private int _graceful=0;
75 private boolean _stopAtShutdown;
76
77
78 public Server()
79 {
80 setServer(this);
81 }
82
83
84
85
86
87 public Server(int port)
88 {
89 setServer(this);
90
91 Connector connector=new SelectChannelConnector();
92 connector.setPort(port);
93 setConnectors(new Connector[]{connector});
94 }
95
96
97
98 public static String getVersion()
99 {
100 return _version;
101 }
102
103
104
105
106
107 public Container getContainer()
108 {
109 return _container;
110 }
111
112
113 public boolean getStopAtShutdown()
114 {
115 return _stopAtShutdown;
116 }
117
118
119 public void setStopAtShutdown(boolean stop)
120 {
121 _stopAtShutdown=stop;
122 if (stop)
123 ShutdownThread.register(this);
124 else
125 ShutdownThread.deregister(this);
126 }
127
128
129
130
131
132 public Connector[] getConnectors()
133 {
134 return _connectors;
135 }
136
137
138 public void addConnector(Connector connector)
139 {
140 setConnectors((Connector[])LazyList.addToArray(getConnectors(), connector, Connector.class));
141 }
142
143
144
145
146
147
148
149 public void removeConnector(Connector connector) {
150 setConnectors((Connector[])LazyList.removeFromArray (getConnectors(), connector));
151 }
152
153
154
155
156
157
158 public void setConnectors(Connector[] connectors)
159 {
160 if (connectors!=null)
161 {
162 for (int i=0;i<connectors.length;i++)
163 connectors[i].setServer(this);
164 }
165
166 _container.update(this, _connectors, connectors, "connector");
167 _connectors = connectors;
168 }
169
170
171
172
173
174 public ThreadPool getThreadPool()
175 {
176 return _threadPool;
177 }
178
179
180
181
182
183 public void setThreadPool(ThreadPool threadPool)
184 {
185 _container.update(this,_threadPool,threadPool, "threadpool",true);
186 _threadPool = threadPool;
187 }
188
189
190 @Override
191 protected void doStart() throws Exception
192 {
193 if (getStopAtShutdown())
194 ShutdownThread.register(this);
195
196 Log.info("jetty-"+_version);
197 HttpGenerator.setServerVersion(_version);
198 MultiException mex=new MultiException();
199
200 Iterator itor = _dependentBeans.iterator();
201 while (itor.hasNext())
202 {
203 try
204 {
205 Object o=itor.next();
206 if (o instanceof LifeCycle)
207 ((LifeCycle)o).start();
208 }
209 catch (Throwable e) {mex.add(e);}
210 }
211
212 if (_threadPool==null)
213 {
214 QueuedThreadPool tp=new QueuedThreadPool();
215 setThreadPool(tp);
216 }
217
218 if (_sessionIdManager!=null)
219 _sessionIdManager.start();
220
221 try
222 {
223 if (_threadPool instanceof LifeCycle)
224 ((LifeCycle)_threadPool).start();
225 }
226 catch(Throwable e) { mex.add(e);}
227
228 try
229 {
230 super.doStart();
231 }
232 catch(Throwable e)
233 {
234 Log.warn("Error starting handlers",e);
235 }
236
237 if (_connectors!=null)
238 {
239 for (int i=0;i<_connectors.length;i++)
240 {
241 try{_connectors[i].start();}
242 catch(Throwable e)
243 {
244 mex.add(e);
245 }
246 }
247 }
248 if (Log.isDebugEnabled())
249 System.err.println(dump());
250
251 mex.ifExceptionThrow();
252 }
253
254
255 @Override
256 protected void doStop() throws Exception
257 {
258 MultiException mex=new MultiException();
259
260 if (_graceful>0)
261 {
262 if (_connectors!=null)
263 {
264 for (int i=_connectors.length;i-->0;)
265 {
266 Log.info("Graceful shutdown {}",_connectors[i]);
267 try{_connectors[i].close();}catch(Throwable e){mex.add(e);}
268 }
269 }
270
271 Handler[] contexts = getChildHandlersByClass(Graceful.class);
272 for (int c=0;c<contexts.length;c++)
273 {
274 Graceful context=(Graceful)contexts[c];
275 Log.info("Graceful shutdown {}",context);
276 context.setShutdown(true);
277 }
278 Thread.sleep(_graceful);
279 }
280
281 if (_connectors!=null)
282 {
283 for (int i=_connectors.length;i-->0;)
284 try{_connectors[i].stop();}catch(Throwable e){mex.add(e);}
285 }
286
287 try {super.doStop(); } catch(Throwable e) { mex.add(e);}
288
289 if (_sessionIdManager!=null)
290 _sessionIdManager.stop();
291
292 try
293 {
294 if (_threadPool instanceof LifeCycle)
295 ((LifeCycle)_threadPool).stop();
296 }
297 catch(Throwable e){mex.add(e);}
298
299 if (!_dependentBeans.isEmpty())
300 {
301 ListIterator itor = _dependentBeans.listIterator(_dependentBeans.size());
302 while (itor.hasPrevious())
303 {
304 try
305 {
306 Object o =itor.previous();
307 if (o instanceof LifeCycle)
308 ((LifeCycle)o).stop();
309 }
310 catch (Throwable e) {mex.add(e);}
311 }
312 }
313
314 mex.ifExceptionThrow();
315 ShutdownThread.deregister(this);
316 }
317
318
319
320
321
322
323
324 public void handle(HttpConnection connection) throws IOException, ServletException
325 {
326 final String target=connection.getRequest().getPathInfo();
327 final Request request=connection.getRequest();
328 final Response response=connection.getResponse();
329
330 if (Log.isDebugEnabled())
331 {
332 Log.debug("REQUEST "+target+" on "+connection);
333 handle(target, request, request, response);
334 Log.debug("RESPONSE "+target+" "+connection.getResponse().getStatus());
335 }
336 else
337 handle(target, request, request, response);
338 }
339
340
341
342
343
344
345
346 public void handleAsync(HttpConnection connection) throws IOException, ServletException
347 {
348 final AsyncContinuation async = connection.getRequest().getAsyncContinuation();
349 final AsyncContinuation.AsyncEventState state = async.getAsyncEventState();
350
351 final Request baseRequest=connection.getRequest();
352 final String path=state.getPath();
353 if (path!=null)
354 {
355
356 baseRequest.setAttribute(AsyncContext.ASYNC_REQUEST_URI,baseRequest.getRequestURI());
357 baseRequest.setAttribute(AsyncContext.ASYNC_QUERY_STRING,baseRequest.getQueryString());
358
359 baseRequest.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,state.getSuspendedContext().getContextPath());
360
361 final String contextPath=state.getServletContext().getContextPath();
362 HttpURI uri = new HttpURI(URIUtil.addPaths(contextPath,path));
363 baseRequest.setUri(uri);
364 baseRequest.setRequestURI(null);
365 baseRequest.setPathInfo(baseRequest.getRequestURI());
366 baseRequest.setQueryString(uri.getQuery());
367 }
368
369 final String target=baseRequest.getPathInfo();
370 final HttpServletRequest request=(HttpServletRequest)async.getRequest();
371 final HttpServletResponse response=(HttpServletResponse)async.getResponse();
372
373 if (Log.isDebugEnabled())
374 {
375 Log.debug("REQUEST "+target+" on "+connection);
376 handle(target, baseRequest, request, response);
377 Log.debug("RESPONSE "+target+" "+connection.getResponse().getStatus());
378 }
379 else
380 handle(target, baseRequest, request, response);
381 }
382
383
384
385
386 public void join() throws InterruptedException
387 {
388 getThreadPool().join();
389 }
390
391
392
393
394
395
396 public SessionIdManager getSessionIdManager()
397 {
398 return _sessionIdManager;
399 }
400
401
402
403
404
405
406 public void setSessionIdManager(SessionIdManager sessionIdManager)
407 {
408 _container.update(this,_sessionIdManager,sessionIdManager, "sessionIdManager",true);
409 _sessionIdManager = sessionIdManager;
410 }
411
412
413 public void setSendServerVersion (boolean sendServerVersion)
414 {
415 _sendServerVersion = sendServerVersion;
416 }
417
418
419 public boolean getSendServerVersion()
420 {
421 return _sendServerVersion;
422 }
423
424
425
426
427
428 public void setSendDateHeader(boolean sendDateHeader)
429 {
430 _sendDateHeader = sendDateHeader;
431 }
432
433
434 public boolean getSendDateHeader()
435 {
436 return _sendDateHeader;
437 }
438
439
440
441
442
443
444
445
446
447 @Deprecated
448 public void addLifeCycle (LifeCycle c)
449 {
450 addBean(c);
451 }
452
453
454
455
456
457
458
459
460
461 public void addBean(Object o)
462 {
463 if (o == null)
464 return;
465
466 if (!_dependentBeans.contains(o))
467 {
468 _dependentBeans.add(o);
469 _container.addBean(o);
470 }
471
472 try
473 {
474 if (isStarted() && o instanceof LifeCycle)
475 ((LifeCycle)o).start();
476 }
477 catch (Exception e)
478 {
479 throw new RuntimeException (e);
480 }
481 }
482
483
484
485
486
487
488
489 public <T> List<T> getBeans(Class<T> clazz)
490 {
491 ArrayList<T> beans = new ArrayList<T>();
492 Iterator<?> iter = _dependentBeans.iterator();
493 while (iter.hasNext())
494 {
495 Object o = iter.next();
496 if (clazz.isInstance(o))
497 beans.add((T)o);
498 }
499 return beans;
500 }
501
502
503
504
505
506
507 @Deprecated
508 public void removeLifeCycle (LifeCycle c)
509 {
510 removeBean(c);
511 }
512
513
514
515
516 public void removeBean (Object o)
517 {
518 if (o == null)
519 return;
520 _dependentBeans.remove(o);
521 _container.removeBean(o);
522 }
523
524
525
526
527
528 public void clearAttributes()
529 {
530 _attributes.clearAttributes();
531 }
532
533
534
535
536
537 public Object getAttribute(String name)
538 {
539 return _attributes.getAttribute(name);
540 }
541
542
543
544
545
546 public Enumeration getAttributeNames()
547 {
548 return AttributesMap.getAttributeNamesCopy(_attributes);
549 }
550
551
552
553
554
555 public void removeAttribute(String name)
556 {
557 _attributes.removeAttribute(name);
558 }
559
560
561
562
563
564 public void setAttribute(String name, Object attribute)
565 {
566 _attributes.setAttribute(name, attribute);
567 }
568
569
570
571
572
573 public int getGracefulShutdown()
574 {
575 return _graceful;
576 }
577
578
579
580
581
582
583
584
585
586
587
588 public void setGracefulShutdown(int timeoutMS)
589 {
590 _graceful=timeoutMS;
591 }
592
593 @Override
594 public String toString()
595 {
596 return this.getClass().getName()+"@"+Integer.toHexString(hashCode());
597 }
598
599
600
601
602
603
604
605 public interface Graceful extends Handler
606 {
607 public void setShutdown(boolean shutdown);
608 }
609
610
611 public static void main(String[] args)
612 {
613 System.err.println(getVersion());
614 }
615 }