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