Mercurial Hosting > luan
comparison src/org/eclipse/jetty/server/Server.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | 700317ba03ad |
comparison
equal
deleted
inserted
replaced
801:6a21393191c1 | 802:3428c60d7cfc |
---|---|
1 // | |
2 // ======================================================================== | |
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. | |
4 // ------------------------------------------------------------------------ | |
5 // All rights reserved. This program and the accompanying materials | |
6 // are made available under the terms of the Eclipse Public License v1.0 | |
7 // and Apache License v2.0 which accompanies this distribution. | |
8 // | |
9 // The Eclipse Public License is available at | |
10 // http://www.eclipse.org/legal/epl-v10.html | |
11 // | |
12 // The Apache License v2.0 is available at | |
13 // http://www.opensource.org/licenses/apache2.0.php | |
14 // | |
15 // You may elect to redistribute this code under either of these licenses. | |
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 | |
25 import javax.servlet.AsyncContext; | |
26 import javax.servlet.ServletException; | |
27 import javax.servlet.http.HttpServletRequest; | |
28 import javax.servlet.http.HttpServletResponse; | |
29 | |
30 import org.eclipse.jetty.http.HttpGenerator; | |
31 import org.eclipse.jetty.http.HttpURI; | |
32 import org.eclipse.jetty.server.handler.HandlerWrapper; | |
33 import org.eclipse.jetty.server.nio.SelectChannelConnector; | |
34 import org.eclipse.jetty.util.Attributes; | |
35 import org.eclipse.jetty.util.AttributesMap; | |
36 import org.eclipse.jetty.util.LazyList; | |
37 import org.eclipse.jetty.util.MultiException; | |
38 import org.eclipse.jetty.util.TypeUtil; | |
39 import org.eclipse.jetty.util.URIUtil; | |
40 import org.eclipse.jetty.util.component.Container; | |
41 import org.eclipse.jetty.util.component.Destroyable; | |
42 import org.eclipse.jetty.util.component.LifeCycle; | |
43 import org.eclipse.jetty.util.log.Log; | |
44 import org.eclipse.jetty.util.log.Logger; | |
45 import org.eclipse.jetty.util.thread.QueuedThreadPool; | |
46 import org.eclipse.jetty.util.thread.ShutdownThread; | |
47 import org.eclipse.jetty.util.thread.ThreadPool; | |
48 | |
49 /* ------------------------------------------------------------ */ | |
50 /** Jetty HTTP Servlet Server. | |
51 * This class is the main class for the Jetty HTTP Servlet server. | |
52 * It aggregates Connectors (HTTP request receivers) and request Handlers. | |
53 * The server is itself a handler and a ThreadPool. Connectors use the ThreadPool methods | |
54 * to run jobs that will eventually call the handle method. | |
55 * | |
56 * @org.apache.xbean.XBean description="Creates an embedded Jetty web server" | |
57 */ | |
58 public class Server extends HandlerWrapper implements Attributes | |
59 { | |
60 private static final Logger LOG = Log.getLogger(Server.class); | |
61 | |
62 private static final String __version; | |
63 static | |
64 { | |
65 if (Server.class.getPackage()!=null && | |
66 "Eclipse.org - Jetty".equals(Server.class.getPackage().getImplementationVendor()) && | |
67 Server.class.getPackage().getImplementationVersion()!=null) | |
68 __version=Server.class.getPackage().getImplementationVersion(); | |
69 else | |
70 __version=System.getProperty("jetty.version","8.y.z-SNAPSHOT"); | |
71 } | |
72 | |
73 private final Container _container=new Container(); | |
74 private final AttributesMap _attributes = new AttributesMap(); | |
75 private ThreadPool _threadPool; | |
76 private Connector[] _connectors; | |
77 private SessionIdManager _sessionIdManager; | |
78 private boolean _sendServerVersion = true; //send Server: header | |
79 private boolean _sendDateHeader = false; //send Date: header | |
80 private int _graceful=0; | |
81 private boolean _stopAtShutdown; | |
82 private boolean _dumpAfterStart=false; | |
83 private boolean _dumpBeforeStop=false; | |
84 private boolean _uncheckedPrintWriter=false; | |
85 | |
86 | |
87 /* ------------------------------------------------------------ */ | |
88 public Server() | |
89 { | |
90 setServer(this); | |
91 } | |
92 | |
93 /* ------------------------------------------------------------ */ | |
94 /** Convenience constructor | |
95 * Creates server and a {@link SelectChannelConnector} at the passed port. | |
96 */ | |
97 public Server(int port) | |
98 { | |
99 setServer(this); | |
100 | |
101 Connector connector=new SelectChannelConnector(); | |
102 connector.setPort(port); | |
103 setConnectors(new Connector[]{connector}); | |
104 } | |
105 | |
106 /* ------------------------------------------------------------ */ | |
107 /** Convenience constructor | |
108 * Creates server and a {@link SelectChannelConnector} at the passed address. | |
109 */ | |
110 public Server(InetSocketAddress addr) | |
111 { | |
112 setServer(this); | |
113 | |
114 Connector connector=new SelectChannelConnector(); | |
115 connector.setHost(addr.getHostName()); | |
116 connector.setPort(addr.getPort()); | |
117 setConnectors(new Connector[]{connector}); | |
118 } | |
119 | |
120 | |
121 /* ------------------------------------------------------------ */ | |
122 public static String getVersion() | |
123 { | |
124 return __version; | |
125 } | |
126 | |
127 /* ------------------------------------------------------------ */ | |
128 /** | |
129 * @return Returns the container. | |
130 */ | |
131 public Container getContainer() | |
132 { | |
133 return _container; | |
134 } | |
135 | |
136 /* ------------------------------------------------------------ */ | |
137 public boolean getStopAtShutdown() | |
138 { | |
139 return _stopAtShutdown; | |
140 } | |
141 | |
142 /* ------------------------------------------------------------ */ | |
143 public void setStopAtShutdown(boolean stop) | |
144 { | |
145 //if we now want to stop | |
146 if (stop) | |
147 { | |
148 //and we weren't stopping before | |
149 if (!_stopAtShutdown) | |
150 { | |
151 //only register to stop if we're already started (otherwise we'll do it in doStart()) | |
152 if (isStarted()) | |
153 ShutdownThread.register(this); | |
154 } | |
155 } | |
156 else | |
157 ShutdownThread.deregister(this); | |
158 | |
159 _stopAtShutdown=stop; | |
160 } | |
161 | |
162 /* ------------------------------------------------------------ */ | |
163 /** | |
164 * @return Returns the connectors. | |
165 */ | |
166 public Connector[] getConnectors() | |
167 { | |
168 return _connectors; | |
169 } | |
170 | |
171 /* ------------------------------------------------------------ */ | |
172 public void addConnector(Connector connector) | |
173 { | |
174 setConnectors((Connector[])LazyList.addToArray(getConnectors(), connector, Connector.class)); | |
175 } | |
176 | |
177 /* ------------------------------------------------------------ */ | |
178 /** | |
179 * Conveniance method which calls {@link #getConnectors()} and {@link #setConnectors(Connector[])} to | |
180 * remove a connector. | |
181 * @param connector The connector to remove. | |
182 */ | |
183 public void removeConnector(Connector connector) { | |
184 setConnectors((Connector[])LazyList.removeFromArray (getConnectors(), connector)); | |
185 } | |
186 | |
187 /* ------------------------------------------------------------ */ | |
188 /** Set the connectors for this server. | |
189 * Each connector has this server set as it's ThreadPool and its Handler. | |
190 * @param connectors The connectors to set. | |
191 */ | |
192 public void setConnectors(Connector[] connectors) | |
193 { | |
194 if (connectors!=null) | |
195 { | |
196 for (int i=0;i<connectors.length;i++) | |
197 connectors[i].setServer(this); | |
198 } | |
199 | |
200 _container.update(this, _connectors, connectors, "connector"); | |
201 _connectors = connectors; | |
202 } | |
203 | |
204 /* ------------------------------------------------------------ */ | |
205 /** | |
206 * @return Returns the threadPool. | |
207 */ | |
208 public ThreadPool getThreadPool() | |
209 { | |
210 return _threadPool; | |
211 } | |
212 | |
213 /* ------------------------------------------------------------ */ | |
214 /** | |
215 * @param threadPool The threadPool to set. | |
216 */ | |
217 public void setThreadPool(ThreadPool threadPool) | |
218 { | |
219 if (_threadPool!=null) | |
220 removeBean(_threadPool); | |
221 _container.update(this, _threadPool, threadPool, "threadpool",false); | |
222 _threadPool = threadPool; | |
223 if (_threadPool!=null) | |
224 addBean(_threadPool); | |
225 } | |
226 | |
227 /** | |
228 * @return true if {@link #dumpStdErr()} is called after starting | |
229 */ | |
230 public boolean isDumpAfterStart() | |
231 { | |
232 return _dumpAfterStart; | |
233 } | |
234 | |
235 /** | |
236 * @param dumpAfterStart true if {@link #dumpStdErr()} is called after starting | |
237 */ | |
238 public void setDumpAfterStart(boolean dumpAfterStart) | |
239 { | |
240 _dumpAfterStart = dumpAfterStart; | |
241 } | |
242 | |
243 /** | |
244 * @return true if {@link #dumpStdErr()} is called before stopping | |
245 */ | |
246 public boolean isDumpBeforeStop() | |
247 { | |
248 return _dumpBeforeStop; | |
249 } | |
250 | |
251 /** | |
252 * @param dumpBeforeStop true if {@link #dumpStdErr()} is called before stopping | |
253 */ | |
254 public void setDumpBeforeStop(boolean dumpBeforeStop) | |
255 { | |
256 _dumpBeforeStop = dumpBeforeStop; | |
257 } | |
258 | |
259 | |
260 | |
261 /* ------------------------------------------------------------ */ | |
262 @Override | |
263 protected void doStart() throws Exception | |
264 { | |
265 if (getStopAtShutdown()) | |
266 { | |
267 ShutdownThread.register(this); | |
268 } | |
269 | |
270 ShutdownMonitor.getInstance().start(); // initialize | |
271 | |
272 LOG.info("jetty-"+__version); | |
273 HttpGenerator.setServerVersion(__version); | |
274 | |
275 MultiException mex=new MultiException(); | |
276 | |
277 if (_threadPool==null) | |
278 setThreadPool(new QueuedThreadPool()); | |
279 | |
280 try | |
281 { | |
282 super.doStart(); | |
283 } | |
284 catch(Throwable e) | |
285 { | |
286 mex.add(e); | |
287 } | |
288 | |
289 if (_connectors!=null && mex.size()==0) | |
290 { | |
291 for (int i=0;i<_connectors.length;i++) | |
292 { | |
293 try{_connectors[i].start();} | |
294 catch(Throwable e) | |
295 { | |
296 mex.add(e); | |
297 } | |
298 } | |
299 } | |
300 | |
301 if (isDumpAfterStart()) | |
302 dumpStdErr(); | |
303 | |
304 mex.ifExceptionThrow(); | |
305 } | |
306 | |
307 /* ------------------------------------------------------------ */ | |
308 @Override | |
309 protected void doStop() throws Exception | |
310 { | |
311 if (isDumpBeforeStop()) | |
312 dumpStdErr(); | |
313 | |
314 MultiException mex=new MultiException(); | |
315 | |
316 if (_graceful>0) | |
317 { | |
318 if (_connectors!=null) | |
319 { | |
320 for (int i=_connectors.length;i-->0;) | |
321 { | |
322 LOG.info("Graceful shutdown {}",_connectors[i]); | |
323 try{_connectors[i].close();}catch(Throwable e){mex.add(e);} | |
324 } | |
325 } | |
326 | |
327 Handler[] contexts = getChildHandlersByClass(Graceful.class); | |
328 for (int c=0;c<contexts.length;c++) | |
329 { | |
330 Graceful context=(Graceful)contexts[c]; | |
331 LOG.info("Graceful shutdown {}",context); | |
332 context.setShutdown(true); | |
333 } | |
334 Thread.sleep(_graceful); | |
335 } | |
336 | |
337 if (_connectors!=null) | |
338 { | |
339 for (int i=_connectors.length;i-->0;) | |
340 try{_connectors[i].stop();}catch(Throwable e){mex.add(e);} | |
341 } | |
342 | |
343 try {super.doStop(); } catch(Throwable e) { mex.add(e);} | |
344 | |
345 mex.ifExceptionThrow(); | |
346 | |
347 if (getStopAtShutdown()) | |
348 ShutdownThread.deregister(this); | |
349 } | |
350 | |
351 /* ------------------------------------------------------------ */ | |
352 /* Handle a request from a connection. | |
353 * Called to handle a request on the connection when either the header has been received, | |
354 * or after the entire request has been received (for short requests of known length), or | |
355 * on the dispatch of an async request. | |
356 */ | |
357 public void handle(AbstractHttpConnection connection) throws IOException, ServletException | |
358 { | |
359 final String target=connection.getRequest().getPathInfo(); | |
360 final Request request=connection.getRequest(); | |
361 final Response response=connection.getResponse(); | |
362 | |
363 if (LOG.isDebugEnabled()) | |
364 { | |
365 LOG.debug("REQUEST "+target+" on "+connection); | |
366 handle(target, request, request, response); | |
367 LOG.debug("RESPONSE "+target+" "+connection.getResponse().getStatus()+" handled="+request.isHandled()); | |
368 } | |
369 else | |
370 handle(target, request, request, response); | |
371 } | |
372 | |
373 /* ------------------------------------------------------------ */ | |
374 /* Handle a request from a connection. | |
375 * Called to handle a request on the connection when either the header has been received, | |
376 * or after the entire request has been received (for short requests of known length), or | |
377 * on the dispatch of an async request. | |
378 */ | |
379 public void handleAsync(AbstractHttpConnection connection) throws IOException, ServletException | |
380 { | |
381 final AsyncContinuation async = connection.getRequest().getAsyncContinuation(); | |
382 final AsyncContinuation.AsyncEventState state = async.getAsyncEventState(); | |
383 | |
384 final Request baseRequest=connection.getRequest(); | |
385 final String path=state.getPath(); | |
386 | |
387 if (path!=null) | |
388 { | |
389 // this is a dispatch with a path | |
390 final String contextPath=state.getServletContext().getContextPath(); | |
391 HttpURI uri = new HttpURI(URIUtil.addPaths(contextPath,path)); | |
392 baseRequest.setUri(uri); | |
393 baseRequest.setRequestURI(null); | |
394 baseRequest.setPathInfo(baseRequest.getRequestURI()); | |
395 if (uri.getQuery()!=null) | |
396 baseRequest.mergeQueryString(uri.getQuery()); //we have to assume dispatch path and query are UTF8 | |
397 } | |
398 | |
399 final String target=baseRequest.getPathInfo(); | |
400 final HttpServletRequest request=(HttpServletRequest)async.getRequest(); | |
401 final HttpServletResponse response=(HttpServletResponse)async.getResponse(); | |
402 | |
403 if (LOG.isDebugEnabled()) | |
404 { | |
405 LOG.debug("REQUEST "+target+" on "+connection); | |
406 handle(target, baseRequest, request, response); | |
407 LOG.debug("RESPONSE "+target+" "+connection.getResponse().getStatus()); | |
408 } | |
409 else | |
410 handle(target, baseRequest, request, response); | |
411 | |
412 } | |
413 | |
414 | |
415 /* ------------------------------------------------------------ */ | |
416 public void join() throws InterruptedException | |
417 { | |
418 getThreadPool().join(); | |
419 } | |
420 | |
421 /* ------------------------------------------------------------ */ | |
422 /* ------------------------------------------------------------ */ | |
423 /** | |
424 * @return Returns the sessionIdManager. | |
425 */ | |
426 public SessionIdManager getSessionIdManager() | |
427 { | |
428 return _sessionIdManager; | |
429 } | |
430 | |
431 /* ------------------------------------------------------------ */ | |
432 /* ------------------------------------------------------------ */ | |
433 /** | |
434 * @param sessionIdManager The sessionIdManager to set. | |
435 */ | |
436 public void setSessionIdManager(SessionIdManager sessionIdManager) | |
437 { | |
438 if (_sessionIdManager!=null) | |
439 removeBean(_sessionIdManager); | |
440 _container.update(this, _sessionIdManager, sessionIdManager, "sessionIdManager",false); | |
441 _sessionIdManager = sessionIdManager; | |
442 if (_sessionIdManager!=null) | |
443 addBean(_sessionIdManager); | |
444 } | |
445 | |
446 /* ------------------------------------------------------------ */ | |
447 public void setSendServerVersion (boolean sendServerVersion) | |
448 { | |
449 _sendServerVersion = sendServerVersion; | |
450 } | |
451 | |
452 /* ------------------------------------------------------------ */ | |
453 public boolean getSendServerVersion() | |
454 { | |
455 return _sendServerVersion; | |
456 } | |
457 | |
458 /* ------------------------------------------------------------ */ | |
459 /** | |
460 * @param sendDateHeader | |
461 */ | |
462 public void setSendDateHeader(boolean sendDateHeader) | |
463 { | |
464 _sendDateHeader = sendDateHeader; | |
465 } | |
466 | |
467 /* ------------------------------------------------------------ */ | |
468 public boolean getSendDateHeader() | |
469 { | |
470 return _sendDateHeader; | |
471 } | |
472 | |
473 /* ------------------------------------------------------------ */ | |
474 /** | |
475 */ | |
476 @Deprecated | |
477 public int getMaxCookieVersion() | |
478 { | |
479 return 1; | |
480 } | |
481 | |
482 /* ------------------------------------------------------------ */ | |
483 /** | |
484 */ | |
485 @Deprecated | |
486 public void setMaxCookieVersion(int maxCookieVersion) | |
487 { | |
488 } | |
489 | |
490 /* ------------------------------------------------------------ */ | |
491 /** | |
492 * Add a LifeCycle object to be started/stopped | |
493 * along with the Server. | |
494 * @deprecated Use {@link #addBean(Object)} | |
495 * @param c | |
496 */ | |
497 @Deprecated | |
498 public void addLifeCycle (LifeCycle c) | |
499 { | |
500 addBean(c); | |
501 } | |
502 | |
503 /* ------------------------------------------------------------ */ | |
504 /** | |
505 * Add an associated bean. | |
506 * The bean will be added to the servers {@link Container} | |
507 * and if it is a {@link LifeCycle} instance, it will be | |
508 * started/stopped along with the Server. Any beans that are also | |
509 * {@link Destroyable}, will be destroyed with the server. | |
510 * @param o the bean object to add | |
511 */ | |
512 @Override | |
513 public boolean addBean(Object o) | |
514 { | |
515 if (super.addBean(o)) | |
516 { | |
517 _container.addBean(o); | |
518 return true; | |
519 } | |
520 return false; | |
521 } | |
522 | |
523 /** | |
524 * Remove a LifeCycle object to be started/stopped | |
525 * along with the Server | |
526 * @deprecated Use {@link #removeBean(Object)} | |
527 */ | |
528 @Deprecated | |
529 public void removeLifeCycle (LifeCycle c) | |
530 { | |
531 removeBean(c); | |
532 } | |
533 | |
534 /* ------------------------------------------------------------ */ | |
535 /** | |
536 * Remove an associated bean. | |
537 */ | |
538 @Override | |
539 public boolean removeBean (Object o) | |
540 { | |
541 if (super.removeBean(o)) | |
542 { | |
543 _container.removeBean(o); | |
544 return true; | |
545 } | |
546 return false; | |
547 } | |
548 | |
549 /* ------------------------------------------------------------ */ | |
550 /* | |
551 * @see org.eclipse.util.AttributesMap#clearAttributes() | |
552 */ | |
553 public void clearAttributes() | |
554 { | |
555 _attributes.clearAttributes(); | |
556 } | |
557 | |
558 /* ------------------------------------------------------------ */ | |
559 /* | |
560 * @see org.eclipse.util.AttributesMap#getAttribute(java.lang.String) | |
561 */ | |
562 public Object getAttribute(String name) | |
563 { | |
564 return _attributes.getAttribute(name); | |
565 } | |
566 | |
567 /* ------------------------------------------------------------ */ | |
568 /* | |
569 * @see org.eclipse.util.AttributesMap#getAttributeNames() | |
570 */ | |
571 public Enumeration getAttributeNames() | |
572 { | |
573 return AttributesMap.getAttributeNamesCopy(_attributes); | |
574 } | |
575 | |
576 /* ------------------------------------------------------------ */ | |
577 /* | |
578 * @see org.eclipse.util.AttributesMap#removeAttribute(java.lang.String) | |
579 */ | |
580 public void removeAttribute(String name) | |
581 { | |
582 _attributes.removeAttribute(name); | |
583 } | |
584 | |
585 /* ------------------------------------------------------------ */ | |
586 /* | |
587 * @see org.eclipse.util.AttributesMap#setAttribute(java.lang.String, java.lang.Object) | |
588 */ | |
589 public void setAttribute(String name, Object attribute) | |
590 { | |
591 _attributes.setAttribute(name, attribute); | |
592 } | |
593 | |
594 /* ------------------------------------------------------------ */ | |
595 /** | |
596 * @return the graceful | |
597 */ | |
598 public int getGracefulShutdown() | |
599 { | |
600 return _graceful; | |
601 } | |
602 | |
603 /* ------------------------------------------------------------ */ | |
604 /** | |
605 * Set graceful shutdown timeout. If set, the internal <code>doStop()</code> method will not immediately stop the | |
606 * server. Instead, all {@link Connector}s will be closed so that new connections will not be accepted | |
607 * and all handlers that implement {@link Graceful} will be put into the shutdown mode so that no new requests | |
608 * will be accepted, but existing requests can complete. The server will then wait the configured timeout | |
609 * before stopping. | |
610 * @param timeoutMS the milliseconds to wait for existing request to complete before stopping the server. | |
611 * | |
612 */ | |
613 public void setGracefulShutdown(int timeoutMS) | |
614 { | |
615 _graceful=timeoutMS; | |
616 } | |
617 | |
618 /* ------------------------------------------------------------ */ | |
619 @Override | |
620 public String toString() | |
621 { | |
622 return this.getClass().getName()+"@"+Integer.toHexString(hashCode()); | |
623 } | |
624 | |
625 /* ------------------------------------------------------------ */ | |
626 @Override | |
627 public void dump(Appendable out,String indent) throws IOException | |
628 { | |
629 dumpThis(out); | |
630 dump(out,indent,TypeUtil.asList(getHandlers()),getBeans(),TypeUtil.asList(_connectors)); | |
631 } | |
632 | |
633 | |
634 /* ------------------------------------------------------------ */ | |
635 public boolean isUncheckedPrintWriter() | |
636 { | |
637 return _uncheckedPrintWriter; | |
638 } | |
639 | |
640 /* ------------------------------------------------------------ */ | |
641 public void setUncheckedPrintWriter(boolean unchecked) | |
642 { | |
643 _uncheckedPrintWriter=unchecked; | |
644 } | |
645 | |
646 | |
647 /* ------------------------------------------------------------ */ | |
648 /* A handler that can be gracefully shutdown. | |
649 * Called by doStop if a {@link #setGracefulShutdown} period is set. | |
650 * TODO move this somewhere better | |
651 */ | |
652 public interface Graceful extends Handler | |
653 { | |
654 public void setShutdown(boolean shutdown); | |
655 } | |
656 | |
657 /* ------------------------------------------------------------ */ | |
658 public static void main(String...args) throws Exception | |
659 { | |
660 System.err.println(getVersion()); | |
661 } | |
662 } |