All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.eclipse.jetty.server.Server Maven / Gradle / Ivy
// ========================================================================
// Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.server;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.servlet.AsyncContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpGenerator;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.AttributesMap;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.MultiException;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.component.Container;
import org.eclipse.jetty.util.component.LifeCycle;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ShutdownThread;
import org.eclipse.jetty.util.thread.ThreadPool;
/* ------------------------------------------------------------ */
/** Jetty HTTP Servlet Server.
* This class is the main class for the Jetty HTTP Servlet server.
* It aggregates Connectors (HTTP request receivers) and request Handlers.
* The server is itself a handler and a ThreadPool. Connectors use the ThreadPool methods
* to run jobs that will eventually call the handle method.
*
* @org.apache.xbean.XBean description="Creates an embedded Jetty web server"
*/
public class Server extends HandlerWrapper implements Attributes
{
private static final String _version;
static
{
if (Server.class.getPackage()!=null && Server.class.getPackage().getImplementationVersion()!=null)
_version=Server.class.getPackage().getImplementationVersion();
else
_version=System.getProperty("jetty.version","8.0.y.z-SNAPSHOT");
}
private final Container _container=new Container();
private final AttributesMap _attributes = new AttributesMap();
private final List _dependentBeans=new ArrayList();
private ThreadPool _threadPool;
private Connector[] _connectors;
private SessionIdManager _sessionIdManager;
private boolean _sendServerVersion = true; //send Server: header
private boolean _sendDateHeader = false; //send Date: header
private int _graceful=0;
private boolean _stopAtShutdown;
private int _maxCookieVersion=1;
/* ------------------------------------------------------------ */
public Server()
{
setServer(this);
}
/* ------------------------------------------------------------ */
/** Convenience constructor
* Creates server and a {@link SelectChannelConnector} at the passed port.
*/
public Server(int port)
{
setServer(this);
Connector connector=new SelectChannelConnector();
connector.setPort(port);
setConnectors(new Connector[]{connector});
}
/* ------------------------------------------------------------ */
/** Convenience constructor
* Creates server and a {@link SelectChannelConnector} at the passed address.
*/
public Server(InetSocketAddress addr)
{
setServer(this);
Connector connector=new SelectChannelConnector();
connector.setHost(addr.getHostName());
connector.setPort(addr.getPort());
setConnectors(new Connector[]{connector});
}
/* ------------------------------------------------------------ */
public static String getVersion()
{
return _version;
}
/* ------------------------------------------------------------ */
/**
* @return Returns the container.
*/
public Container getContainer()
{
return _container;
}
/* ------------------------------------------------------------ */
public boolean getStopAtShutdown()
{
return _stopAtShutdown;
}
/* ------------------------------------------------------------ */
public void setStopAtShutdown(boolean stop)
{
_stopAtShutdown=stop;
if (stop)
ShutdownThread.register(this);
else
ShutdownThread.deregister(this);
}
/* ------------------------------------------------------------ */
/**
* @return Returns the connectors.
*/
public Connector[] getConnectors()
{
return _connectors;
}
/* ------------------------------------------------------------ */
public void addConnector(Connector connector)
{
setConnectors((Connector[])LazyList.addToArray(getConnectors(), connector, Connector.class));
}
/* ------------------------------------------------------------ */
/**
* Conveniance method which calls {@link #getConnectors()} and {@link #setConnectors(Connector[])} to
* remove a connector.
* @param connector The connector to remove.
*/
public void removeConnector(Connector connector) {
setConnectors((Connector[])LazyList.removeFromArray (getConnectors(), connector));
}
/* ------------------------------------------------------------ */
/** Set the connectors for this server.
* Each connector has this server set as it's ThreadPool and its Handler.
* @param connectors The connectors to set.
*/
public void setConnectors(Connector[] connectors)
{
if (connectors!=null)
{
for (int i=0;i itor = _dependentBeans.iterator();
while (itor.hasNext())
{
try
{
Object o=itor.next();
if (o instanceof LifeCycle)
((LifeCycle)o).start();
}
catch (Throwable e) {mex.add(e);}
}
if (_sessionIdManager!=null)
_sessionIdManager.start();
try
{
if (_threadPool instanceof LifeCycle)
((LifeCycle)_threadPool).start();
}
catch(Throwable e) { mex.add(e);}
try
{
super.doStart();
}
catch(Throwable e)
{
Log.warn("Error starting handlers",e);
}
if (_connectors!=null)
{
for (int i=0;i<_connectors.length;i++)
{
try{_connectors[i].start();}
catch(Throwable e)
{
mex.add(e);
}
}
}
if (Log.isDebugEnabled())
System.err.println(dump());
mex.ifExceptionThrow();
}
/* ------------------------------------------------------------ */
@Override
protected void doStop() throws Exception
{
MultiException mex=new MultiException();
if (_graceful>0)
{
if (_connectors!=null)
{
for (int i=_connectors.length;i-->0;)
{
Log.info("Graceful shutdown {}",_connectors[i]);
try{_connectors[i].close();}catch(Throwable e){mex.add(e);}
}
}
Handler[] contexts = getChildHandlersByClass(Graceful.class);
for (int c=0;c0;)
try{_connectors[i].stop();}catch(Throwable e){mex.add(e);}
}
try {super.doStop(); } catch(Throwable e) { mex.add(e);}
if (_sessionIdManager!=null)
_sessionIdManager.stop();
try
{
if (_threadPool instanceof LifeCycle)
((LifeCycle)_threadPool).stop();
}
catch(Throwable e){mex.add(e);}
if (!_dependentBeans.isEmpty())
{
ListIterator itor = _dependentBeans.listIterator(_dependentBeans.size());
while (itor.hasPrevious())
{
try
{
Object o =itor.previous();
if (o instanceof LifeCycle)
((LifeCycle)o).stop();
}
catch (Throwable e) {mex.add(e);}
}
}
mex.ifExceptionThrow();
if (getStopAtShutdown())
ShutdownThread.deregister(this);
}
/* ------------------------------------------------------------ */
/* Handle a request from a connection.
* Called to handle a request on the connection when either the header has been received,
* or after the entire request has been received (for short requests of known length), or
* on the dispatch of an async request.
*/
public void handle(HttpConnection connection) throws IOException, ServletException
{
final String target=connection.getRequest().getPathInfo();
final Request request=connection.getRequest();
final Response response=connection.getResponse();
if (Log.isDebugEnabled())
{
Log.debug("REQUEST "+target+" on "+connection);
handle(target, request, request, response);
Log.debug("RESPONSE "+target+" "+connection.getResponse().getStatus());
}
else
handle(target, request, request, response);
}
/* ------------------------------------------------------------ */
/* Handle a request from a connection.
* Called to handle a request on the connection when either the header has been received,
* or after the entire request has been received (for short requests of known length), or
* on the dispatch of an async request.
*/
public void handleAsync(HttpConnection connection) throws IOException, ServletException
{
final AsyncContinuation async = connection.getRequest().getAsyncContinuation();
final AsyncContinuation.AsyncEventState state = async.getAsyncEventState();
final Request baseRequest=connection.getRequest();
final String path=state.getPath();
if (path!=null)
{
// this is a dispatch with a path
baseRequest.setAttribute(AsyncContext.ASYNC_REQUEST_URI,baseRequest.getRequestURI());
baseRequest.setAttribute(AsyncContext.ASYNC_QUERY_STRING,baseRequest.getQueryString());
baseRequest.setAttribute(AsyncContext.ASYNC_CONTEXT_PATH,state.getSuspendedContext().getContextPath());
final String contextPath=state.getServletContext().getContextPath();
HttpURI uri = new HttpURI(URIUtil.addPaths(contextPath,path));
baseRequest.setUri(uri);
baseRequest.setRequestURI(null);
baseRequest.setPathInfo(baseRequest.getRequestURI());
if (uri.getQuery()!=null)
baseRequest.mergeQueryString(uri.getQuery());
}
final String target=baseRequest.getPathInfo();
final HttpServletRequest request=(HttpServletRequest)async.getRequest();
final HttpServletResponse response=(HttpServletResponse)async.getResponse();
if (Log.isDebugEnabled())
{
Log.debug("REQUEST "+target+" on "+connection);
handle(target, baseRequest, request, response);
Log.debug("RESPONSE "+target+" "+connection.getResponse().getStatus());
}
else
handle(target, baseRequest, request, response);
}
/* ------------------------------------------------------------ */
public void join() throws InterruptedException
{
getThreadPool().join();
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/**
* @return Returns the sessionIdManager.
*/
public SessionIdManager getSessionIdManager()
{
return _sessionIdManager;
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/**
* @param sessionIdManager The sessionIdManager to set.
*/
public void setSessionIdManager(SessionIdManager sessionIdManager)
{
_container.update(this,_sessionIdManager,sessionIdManager, "sessionIdManager",true);
_sessionIdManager = sessionIdManager;
}
/* ------------------------------------------------------------ */
public void setSendServerVersion (boolean sendServerVersion)
{
_sendServerVersion = sendServerVersion;
}
/* ------------------------------------------------------------ */
public boolean getSendServerVersion()
{
return _sendServerVersion;
}
/* ------------------------------------------------------------ */
/**
* @param sendDateHeader
*/
public void setSendDateHeader(boolean sendDateHeader)
{
_sendDateHeader = sendDateHeader;
}
/* ------------------------------------------------------------ */
public boolean getSendDateHeader()
{
return _sendDateHeader;
}
/* ------------------------------------------------------------ */
/** Get the maximum cookie version.
* @return the maximum set-cookie version sent by this server
*/
public int getMaxCookieVersion()
{
return _maxCookieVersion;
}
/* ------------------------------------------------------------ */
/** Set the maximum cookie version.
* @param maxCookieVersion the maximum set-cookie version sent by this server
*/
public void setMaxCookieVersion(int maxCookieVersion)
{
_maxCookieVersion = maxCookieVersion;
}
/* ------------------------------------------------------------ */
/**
* Add a LifeCycle object to be started/stopped
* along with the Server.
* @deprecated Use {@link #addBean(Object)}
* @param c
*/
@Deprecated
public void addLifeCycle (LifeCycle c)
{
addBean(c);
}
/* ------------------------------------------------------------ */
/**
* Add an associated bean.
* The bean will be added to the servers {@link Container}
* and if it is a {@link LifeCycle} instance, it will be
* started/stopped along with the Server.
* @param o the bean object to add
*/
public void addBean(Object o)
{
if (o == null)
return;
if (!_dependentBeans.contains(o))
{
_dependentBeans.add(o);
_container.addBean(o);
}
try
{
if (isStarted() && o instanceof LifeCycle)
((LifeCycle)o).start();
}
catch (Exception e)
{
throw new RuntimeException (e);
}
}
/* ------------------------------------------------------------ */
/** Get dependent beans of a specific class
* @see #addBean(Object)
* @param clazz
* @return List of beans.
*/
public List getBeans(Class clazz)
{
ArrayList beans = new ArrayList();
Iterator> iter = _dependentBeans.iterator();
while (iter.hasNext())
{
Object o = iter.next();
if (clazz.isInstance(o))
beans.add((T)o);
}
return beans;
}
/* ------------------------------------------------------------ */
/** Get dependent bean of a specific class.
* If more than one bean of the type exist, the first is returned.
* @see #addBean(Object)
* @param clazz
* @return bean or null
*/
public T getBean(Class clazz)
{
Iterator> iter = _dependentBeans.iterator();
T t=null;
int count=0;
while (iter.hasNext())
{
Object o = iter.next();
if (clazz.isInstance(o))
{
count++;
if (t==null)
t=(T)o;
}
}
if (count>1)
Log.debug("getBean({}) 1 of {}",clazz.getName(),count);
return t;
}
/**
* Remove a LifeCycle object to be started/stopped
* along with the Server
* @deprecated Use {@link #removeBean(Object)}
*/
@Deprecated
public void removeLifeCycle (LifeCycle c)
{
removeBean(c);
}
/**
* Remove an associated bean.
*/
public void removeBean (Object o)
{
if (o == null)
return;
_dependentBeans.remove(o);
_container.removeBean(o);
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.util.AttributesMap#clearAttributes()
*/
public void clearAttributes()
{
_attributes.clearAttributes();
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.util.AttributesMap#getAttribute(java.lang.String)
*/
public Object getAttribute(String name)
{
return _attributes.getAttribute(name);
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.util.AttributesMap#getAttributeNames()
*/
public Enumeration getAttributeNames()
{
return AttributesMap.getAttributeNamesCopy(_attributes);
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.util.AttributesMap#removeAttribute(java.lang.String)
*/
public void removeAttribute(String name)
{
_attributes.removeAttribute(name);
}
/* ------------------------------------------------------------ */
/*
* @see org.eclipse.util.AttributesMap#setAttribute(java.lang.String, java.lang.Object)
*/
public void setAttribute(String name, Object attribute)
{
_attributes.setAttribute(name, attribute);
}
/* ------------------------------------------------------------ */
/**
* @return the graceful
*/
public int getGracefulShutdown()
{
return _graceful;
}
/* ------------------------------------------------------------ */
/**
* Set graceful shutdown timeout. If set, the internal doStop()
method will not immediately stop the
* server. Instead, all {@link Connector}s will be closed so that new connections will not be accepted
* and all handlers that implement {@link Graceful} will be put into the shutdown mode so that no new requests
* will be accepted, but existing requests can complete. The server will then wait the configured timeout
* before stopping.
* @param timeoutMS the milliseconds to wait for existing request to complete before stopping the server.
*
*/
public void setGracefulShutdown(int timeoutMS)
{
_graceful=timeoutMS;
}
/* ------------------------------------------------------------ */
@Override
public String toString()
{
return this.getClass().getName()+"@"+Integer.toHexString(hashCode());
}
/* ------------------------------------------------------------ */
@Override
protected void dump(Appendable out,String indent) throws IOException
{
out.append(toString()).append(isStarted()?" started":" STOPPED").append('\n');
if (_connectors != null)
for (Connector c : _connectors)
out.append(" +-").append(String.valueOf(c)).append('\n');
if (_threadPool != null)
out.append(" +-").append(String.valueOf(_threadPool)).append('\n');
dumpHandlers(out,indent);
}
/* ------------------------------------------------------------ */
/* A handler that can be gracefully shutdown.
* Called by doStop if a {@link #setGracefulShutdown} period is set.
* TODO move this somewhere better
*/
public interface Graceful extends Handler
{
public void setShutdown(boolean shutdown);
}
/* ------------------------------------------------------------ */
public static void main(String[] args)
{
System.err.println(getVersion());
}
}