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