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