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