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