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