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