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