1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty;
16
17 import java.io.IOException;
18 import java.lang.reflect.Method;
19 import java.util.ArrayList;
20 import java.util.Collection;
21 import java.util.Enumeration;
22 import java.util.Iterator;
23 import java.util.List;
24 import java.util.ListIterator;
25
26 import javax.servlet.ServletException;
27
28 import org.mortbay.component.Container;
29 import org.mortbay.component.LifeCycle;
30 import org.mortbay.jetty.bio.SocketConnector;
31 import org.mortbay.jetty.handler.HandlerCollection;
32 import org.mortbay.jetty.handler.HandlerWrapper;
33 import org.mortbay.jetty.nio.SelectChannelConnector;
34 import org.mortbay.jetty.security.UserRealm;
35 import org.mortbay.log.Log;
36 import org.mortbay.thread.QueuedThreadPool;
37 import org.mortbay.thread.ThreadPool;
38 import org.mortbay.util.Attributes;
39 import org.mortbay.util.AttributesMap;
40 import org.mortbay.util.LazyList;
41 import org.mortbay.util.MultiException;
42
43
44
45
46
47
48
49
50
51
52 public class Server extends HandlerWrapper implements Attributes
53 {
54 private static ShutdownHookThread hookThread = new ShutdownHookThread();
55 private static String _version = (Server.class.getPackage()!=null && Server.class.getPackage().getImplementationVersion()!=null)
56 ?Server.class.getPackage().getImplementationVersion()
57 :"7.0.x";
58
59 private ThreadPool _threadPool;
60 private Connector[] _connectors;
61 private UserRealm[] _realms;
62 private Container _container=new Container();
63 private SessionIdManager _sessionIdManager;
64 private boolean _sendServerVersion = true;
65 private boolean _sendDateHeader = false;
66 private AttributesMap _attributes = new AttributesMap();
67 private List _dependentLifeCycles=new ArrayList();
68 private int _graceful=0;
69
70
71 public Server()
72 {
73 setServer(this);
74 }
75
76
77
78
79
80 public Server(int port)
81 {
82 setServer(this);
83
84 Connector connector=new SelectChannelConnector();
85 connector.setPort(port);
86 setConnectors(new Connector[]{connector});
87 }
88
89
90
91 public static String getVersion()
92 {
93 return _version;
94 }
95
96
97
98
99
100 public Container getContainer()
101 {
102 return _container;
103 }
104
105
106 public boolean getStopAtShutdown()
107 {
108 return hookThread.contains(this);
109 }
110
111
112 public void setStopAtShutdown(boolean stop)
113 {
114 if (stop)
115 hookThread.add(this);
116 else
117 hookThread.remove(this);
118 }
119
120
121
122
123
124 public Connector[] getConnectors()
125 {
126 return _connectors;
127 }
128
129
130
131 public void addConnector(Connector connector)
132 {
133 setConnectors((Connector[])LazyList.addToArray(getConnectors(), connector, Connector.class));
134 }
135
136
137
138
139
140
141
142 public void removeConnector(Connector connector) {
143 setConnectors((Connector[])LazyList.removeFromArray (getConnectors(), connector));
144 }
145
146
147
148
149
150
151 public void setConnectors(Connector[] connectors)
152 {
153 if (connectors!=null)
154 {
155 for (int i=0;i<connectors.length;i++)
156 connectors[i].setServer(this);
157 }
158
159 _container.update(this, _connectors, connectors, "connector");
160 _connectors = connectors;
161 }
162
163
164
165
166
167 public ThreadPool getThreadPool()
168 {
169 return _threadPool;
170 }
171
172
173
174
175
176 public void setThreadPool(ThreadPool threadPool)
177 {
178 _container.update(this,_threadPool,threadPool, "threadpool",true);
179 _threadPool = threadPool;
180 }
181
182
183 protected void doStart() throws Exception
184 {
185 Log.info("jetty-"+_version);
186 HttpGenerator.setServerVersion(_version);
187 MultiException mex=new MultiException();
188
189 for (int i=0;_realms !=null && i<_realms.length; i++)
190 {
191 if (_realms[i] instanceof LifeCycle)
192 ((LifeCycle)_realms[i]).start();
193 }
194
195 Iterator itor = _dependentLifeCycles.iterator();
196 while (itor.hasNext())
197 {
198 try
199 {
200 ((LifeCycle)itor.next()).start();
201 }
202 catch (Throwable e) {mex.add(e);}
203 }
204
205 if (_threadPool==null)
206 {
207 QueuedThreadPool tp=new QueuedThreadPool();
208 setThreadPool(tp);
209 }
210
211 if (_sessionIdManager!=null)
212 _sessionIdManager.start();
213
214 try
215 {
216 if (_threadPool instanceof LifeCycle)
217 ((LifeCycle)_threadPool).start();
218 }
219 catch(Throwable e) { mex.add(e);}
220
221 try
222 {
223 super.doStart();
224 }
225 catch(Throwable e)
226 {
227 Log.warn("Error starting handlers",e);
228 }
229
230 if (_connectors!=null)
231 {
232 for (int i=0;i<_connectors.length;i++)
233 {
234 try{_connectors[i].start();}
235 catch(Throwable e)
236 {
237 mex.add(e);
238 }
239 }
240 }
241 mex.ifExceptionThrow();
242 }
243
244
245 protected void doStop() throws Exception
246 {
247 MultiException mex=new MultiException();
248
249 for (int i=0;_realms !=null && i<_realms.length; i++)
250 {
251 if (_realms[i] instanceof LifeCycle)
252 ((LifeCycle)_realms[i]).stop();
253 }
254
255 if (_graceful>0)
256 {
257 if (_connectors!=null)
258 {
259 for (int i=_connectors.length;i-->0;)
260 {
261 Log.info("Graceful shutdown {}",_connectors[i]);
262 try{_connectors[i].close();}catch(Throwable e){mex.add(e);}
263 }
264 }
265
266 Handler[] contexts = getChildHandlersByClass(Graceful.class);
267 for (int c=0;c<contexts.length;c++)
268 {
269 Graceful context=(Graceful)contexts[c];
270 Log.info("Graceful shutdown {}",context);
271 context.setShutdown(true);
272 }
273 Thread.sleep(_graceful);
274 }
275
276 if (_connectors!=null)
277 {
278 for (int i=_connectors.length;i-->0;)
279 try{_connectors[i].stop();}catch(Throwable e){mex.add(e);}
280 }
281
282 try {super.doStop(); } catch(Throwable e) { mex.add(e);}
283
284 if (_sessionIdManager!=null)
285 _sessionIdManager.stop();
286
287 try
288 {
289 if (_threadPool instanceof LifeCycle)
290 ((LifeCycle)_threadPool).stop();
291 }
292 catch(Throwable e){mex.add(e);}
293
294 if (!_dependentLifeCycles.isEmpty())
295 {
296 ListIterator itor = _dependentLifeCycles.listIterator(_dependentLifeCycles.size());
297 while (itor.hasPrevious())
298 {
299 try
300 {
301 ((LifeCycle)itor.previous()).stop();
302 }
303 catch (Throwable e) {mex.add(e);}
304 }
305 }
306
307 mex.ifExceptionThrow();
308 }
309
310
311
312
313
314
315 public void handle(HttpConnection connection) throws IOException, ServletException
316 {
317 String target=connection.getRequest().getPathInfo();
318 if (Log.isDebugEnabled())
319 {
320 Log.debug("REQUEST "+target+" on "+connection);
321 handle(target, connection.getRequest(), connection.getResponse(), Handler.REQUEST);
322 Log.debug("RESPONSE "+target+" "+connection.getResponse().getStatus());
323 }
324 else
325 handle(target, connection.getRequest(), connection.getResponse(), Handler.REQUEST);
326 }
327
328
329 public void join() throws InterruptedException
330 {
331 getThreadPool().join();
332 }
333
334
335
336
337
338 public UserRealm[] getUserRealms()
339 {
340 return _realms;
341 }
342
343
344
345
346
347 public void setUserRealms(UserRealm[] realms)
348 {
349 _container.update(this,_realms,realms, "realm",true);
350 _realms=realms;
351 }
352
353
354 public void addUserRealm(UserRealm realm)
355 {
356 setUserRealms((UserRealm[])LazyList.addToArray(getUserRealms(), realm, UserRealm.class));
357 }
358
359
360 public void removeUserRealm(UserRealm realm)
361 {
362 setUserRealms((UserRealm[])LazyList.removeFromArray(getUserRealms(), realm));
363 }
364
365
366
367
368
369
370 public SessionIdManager getSessionIdManager()
371 {
372 return _sessionIdManager;
373 }
374
375
376
377
378
379
380 public void setSessionIdManager(SessionIdManager sessionIdManager)
381 {
382 _container.update(this,_sessionIdManager,sessionIdManager, "sessionIdManager",true);
383 _sessionIdManager = sessionIdManager;
384 }
385
386
387 public void setSendServerVersion (boolean sendServerVersion)
388 {
389 _sendServerVersion = sendServerVersion;
390 }
391
392
393 public boolean getSendServerVersion()
394 {
395 return _sendServerVersion;
396 }
397
398
399
400
401
402 public void setSendDateHeader(boolean sendDateHeader)
403 {
404 _sendDateHeader = sendDateHeader;
405 }
406
407
408 public boolean getSendDateHeader()
409 {
410 return _sendDateHeader;
411 }
412
413
414
415
416
417
418
419 public void addLifeCycle (LifeCycle c)
420 {
421 if (c == null)
422 return;
423 if (!_dependentLifeCycles.contains(c))
424 {
425 _dependentLifeCycles.add(c);
426 _container.addBean(c);
427 }
428 try
429 {
430 if (isStarted())
431 ((LifeCycle)c).start();
432 }
433 catch (Exception e)
434 {
435 throw new RuntimeException (e);
436 }
437 }
438
439
440
441
442
443
444 public void removeLifeCycle (LifeCycle c)
445 {
446 if (c == null)
447 return;
448 _dependentLifeCycles.remove(c);
449 _container.removeBean(c);
450 }
451
452
453
454
455
456
457
458
459
460
461
462 private static class ShutdownHookThread extends Thread
463 {
464 private boolean hooked = false;
465 private ArrayList servers = new ArrayList();
466
467
468
469
470
471
472 private void createShutdownHook()
473 {
474 if (!Boolean.getBoolean("JETTY_NO_SHUTDOWN_HOOK") && !hooked)
475 {
476 try
477 {
478 Method shutdownHook = java.lang.Runtime.class.getMethod("addShutdownHook", new Class[]
479 { java.lang.Thread.class});
480 shutdownHook.invoke(Runtime.getRuntime(), new Object[]
481 { this});
482 this.hooked = true;
483 }
484 catch (Exception e)
485 {
486 if (Log.isDebugEnabled())
487 Log.debug("No shutdown hook in JVM ", e);
488 }
489 }
490 }
491
492
493
494
495 public boolean add(Server server)
496 {
497 createShutdownHook();
498 return this.servers.add(server);
499 }
500
501
502
503
504 public boolean contains(Server server)
505 {
506 return this.servers.contains(server);
507 }
508
509
510
511
512 public boolean addAll(Collection c)
513 {
514 createShutdownHook();
515 return this.servers.addAll(c);
516 }
517
518
519
520
521 public void clear()
522 {
523 createShutdownHook();
524 this.servers.clear();
525 }
526
527
528
529
530 public boolean remove(Server server)
531 {
532 createShutdownHook();
533 return this.servers.remove(server);
534 }
535
536
537
538
539 public boolean removeAll(Collection c)
540 {
541 createShutdownHook();
542 return this.servers.removeAll(c);
543 }
544
545
546
547
548 public void run()
549 {
550 setName("Shutdown");
551 Log.info("Shutdown hook executing");
552 Iterator it = servers.iterator();
553 while (it.hasNext())
554 {
555 Server svr = (Server) it.next();
556 if (svr == null)
557 continue;
558 try
559 {
560 svr.stop();
561 }
562 catch (Exception e)
563 {
564 Log.warn(e);
565 }
566 Log.info("Shutdown hook complete");
567
568
569 try
570 {
571 Thread.sleep(1000);
572 }
573 catch (Exception e)
574 {
575 Log.warn(e);
576 }
577 }
578 }
579 }
580
581
582
583
584
585
586
587 public void addHandler(Handler handler)
588 {
589 if (getHandler() == null)
590 setHandler(handler);
591 else if (getHandler() instanceof HandlerCollection)
592 ((HandlerCollection)getHandler()).addHandler(handler);
593 else
594 {
595 HandlerCollection collection=new HandlerCollection();
596 collection.setHandlers(new Handler[]{getHandler(),handler});
597 setHandler(collection);
598 }
599 }
600
601
602
603
604 public void removeHandler(Handler handler)
605 {
606 if (getHandler() instanceof HandlerCollection)
607 ((HandlerCollection)getHandler()).removeHandler(handler);
608 }
609
610
611
612
613 public Handler[] getHandlers()
614 {
615 if (getHandler() instanceof HandlerCollection)
616 return ((HandlerCollection)getHandler()).getHandlers();
617
618 return null;
619 }
620
621
622
623
624 public void setHandlers(Handler[] handlers)
625 {
626 HandlerCollection collection;
627 if (getHandler() instanceof HandlerCollection)
628 collection=(HandlerCollection)getHandler();
629 else
630 {
631 collection=new HandlerCollection();
632 setHandler(collection);
633 }
634
635 collection.setHandlers(handlers);
636 }
637
638
639
640
641
642 public void clearAttributes()
643 {
644 _attributes.clearAttributes();
645 }
646
647
648
649
650
651 public Object getAttribute(String name)
652 {
653 return _attributes.getAttribute(name);
654 }
655
656
657
658
659
660 public Enumeration getAttributeNames()
661 {
662 return AttributesMap.getAttributeNamesCopy(_attributes);
663 }
664
665
666
667
668
669 public void removeAttribute(String name)
670 {
671 _attributes.removeAttribute(name);
672 }
673
674
675
676
677
678 public void setAttribute(String name, Object attribute)
679 {
680 _attributes.setAttribute(name, attribute);
681 }
682
683
684
685
686
687 public int getGracefulShutdown()
688 {
689 return _graceful;
690 }
691
692
693
694
695
696
697
698
699
700
701
702 public void setGracefulShutdown(int timeoutMS)
703 {
704 _graceful=timeoutMS;
705 }
706
707
708
709
710
711 public interface Graceful
712 {
713 public void setShutdown(boolean shutdown);
714 }
715 }