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