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