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 }