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