
net.lightbody.bmp.proxy.jetty.http.HttpServer Maven / Gradle / Ivy
// ========================================================================
// $Id: HttpServer.java,v 1.70 2005/12/04 11:43:21 gregwilkins Exp $
// Copyright 1999-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
package net.lightbody.bmp.proxy.jetty.http;
import net.lightbody.bmp.proxy.jetty.http.handler.DumpHandler;
import net.lightbody.bmp.proxy.jetty.http.handler.NotFoundHandler;
import net.lightbody.bmp.proxy.jetty.http.handler.ResourceHandler;
import net.lightbody.bmp.proxy.jetty.log.LogFactory;
import net.lightbody.bmp.proxy.jetty.util.*;
import org.apache.commons.logging.Log;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.net.MalformedURLException;
import java.util.*;
/* ------------------------------------------------------------ */
/** HTTP Server.
* Services HTTP requests by maintaining a mapping between
* a collection of HttpListeners which generate requests and
* HttpContexts which contain collections of HttpHandlers.
*
* This class is configured by API calls. The
* org.mortbay.jetty.Server class uses XML configuration files to
* configure instances of this class.
*
* The HttpServer implements the BeanContext API so that membership
* events may be generated for HttpListeners, HttpContexts and WebApplications.
*
* @see HttpContext
* @see HttpHandler
* @see HttpConnection
* @see HttpListener
* @see net.lightbody.bmp.proxy.jetty.jetty.Server
* @version $Id: HttpServer.java,v 1.70 2005/12/04 11:43:21 gregwilkins Exp $
* @author Greg Wilkins (gregw)
*/
public class HttpServer extends Container
implements LifeCycle,
EventProvider,
Serializable
{
private static Log log = LogFactory.getLog(HttpServer.class);
/* ------------------------------------------------------------ */
private static WeakHashMap __servers = new WeakHashMap();
private static Collection __roServers =
Collections.unmodifiableCollection(__servers.keySet());
private static String[] __noVirtualHost=new String[1];
/* ------------------------------------------------------------ */
/** Get HttpServer Collection.
* Get a collection of all known HttpServers. Servers can be
* removed from this list with the setAnonymous call.
* @return Collection of all servers.
*/
public static Collection getHttpServers()
{
return __roServers;
}
/* ------------------------------------------------------------ */
/**
* @deprecated User getHttpServers()
*/
public static List getHttpServerList()
{
return new ArrayList(__roServers);
}
/* ------------------------------------------------------------ */
private List _listeners = new ArrayList(3);
private HashMap _realmMap = new HashMap(3);
private StringMap _virtualHostMap = new StringMap();
private boolean _trace=false;
private RequestLog _requestLog;
private int _requestsPerGC ;
private boolean _resolveRemoteHost =false;
private String[] _serverClasses;
private String[] _systemClasses;
private transient int _gcRequests;
private transient HttpContext _notFoundContext=null;
private transient boolean _gracefulStop;
/* ------------------------------------------------------------ */
/** Constructor.
*/
public HttpServer()
{
this(false);
}
/* ------------------------------------------------------------ */
/** Constructor.
* @param anonymous If true, the server is not included in the
* static server lists and stopAll methods.
*/
public HttpServer(boolean anonymous)
{
setAnonymous(anonymous);
_virtualHostMap.setIgnoreCase(true);
}
/* ------------------------------------------------------------ */
private void readObject(java.io.ObjectInputStream in)
throws IOException, ClassNotFoundException
{
in.defaultReadObject();
HttpListener[] listeners=getListeners();
HttpContext[] contexts=getContexts();
_listeners.clear();
_virtualHostMap.clear();
setContexts(contexts);
setListeners(listeners);
_statsLock=new Object[0];
}
/* ------------------------------------------------------------ */
/**
* @param anonymous If true, the server is not included in the
* static server lists and stopAll methods.
*/
public void setAnonymous(boolean anonymous)
{
if (anonymous)
__servers.remove(this);
else
__servers.put(this,__servers);
}
/* ------------------------------------------------------------ */
public void setStopGracefully(boolean graceful)
{
_gracefulStop=graceful;
}
/* ------------------------------------------------------------ */
public boolean getStopGracefully()
{
return _gracefulStop;
}
/* ------------------------------------------------------------ */
/**
* @param listeners Array of HttpListeners.
*/
public void setListeners(HttpListener[] listeners)
{
List old = new ArrayList(_listeners);
for (int i=0;i=contextList.size())
return null;
hc=(HttpContext)contextList.get(i);
}
}
return hc;
}
/* ------------------------------------------------------------ */
/** Get or create context.
* @param virtualHost The virtual host or null for all hosts.
* @param contextPathSpec
* @return HttpContext. If multiple contexts exist for the same
* virtualHost and pathSpec, the most recently added context is returned.
* If no context exists, a new context is created by a call to newHttpContext.
*/
public HttpContext getContext(String virtualHost, String contextPathSpec)
{
HttpContext hc=null;
contextPathSpec=HttpContext.canonicalContextPathSpec(contextPathSpec);
PathMap contextMap=(PathMap)_virtualHostMap.get(virtualHost);
if (contextMap!=null)
{
List contextList = (List)contextMap.get(contextPathSpec);
if (contextList!=null && contextList.size()>0)
hc=(HttpContext)contextList.get(contextList.size()-1);
}
if (hc==null)
hc=addContext(virtualHost,contextPathSpec);
return hc;
}
/* ------------------------------------------------------------ */
/** Get or create context.
* @param contextPathSpec Path specification relative to the context path.
* @return The HttpContext If multiple contexts exist for the same
* pathSpec, the most recently added context is returned.
* If no context exists, a new context is created by a call to newHttpContext.
*/
public HttpContext getContext(String contextPathSpec)
{
return getContext(null,contextPathSpec);
}
/* ------------------------------------------------------------ */
/** Create a new HttpContext.
* Specialized HttpServer classes may override this method to
* return subclasses of HttpContext.
* @return A new instance of HttpContext or a subclass of HttpContext
*/
protected HttpContext newHttpContext()
{
return new HttpContext();
}
/* ------------------------------------------------------------ */
synchronized void addMapping(String virtualHost, HttpContext context)
{
// Get the map of contexts
PathMap contextMap=(PathMap)_virtualHostMap.get(virtualHost);
if (contextMap==null)
{
contextMap=new PathMap(7);
_virtualHostMap.put(virtualHost,contextMap);
}
// Generalize contextPath
String contextPathSpec=
HttpContext.canonicalContextPathSpec(context.getContextPath());
// Get the list of contexts at this path
List contextList = (List)contextMap.get(contextPathSpec);
if (contextList==null)
{
contextList=new ArrayList(1);
contextMap.put(contextPathSpec,contextList);
}
// Add the context to the list
contextList.add(context);
if(log.isDebugEnabled())log.debug("Added "+context+" for host "+(virtualHost==null?"*":virtualHost));
}
/* ------------------------------------------------------------ */
synchronized void addMappings(HttpContext context)
{
if (context==_notFoundContext)
return;
String[] hosts=context.getVirtualHosts();
if (hosts==null || hosts.length==0)
hosts = __noVirtualHost;
// For each host name
for (int h=0;h0 && _gcRequests++>_requestsPerGC)
{
_gcRequests=0;
System.gc();
}
while (true)
{
PathMap contextMap=(PathMap)_virtualHostMap.get(host);
if (contextMap!=null)
{
List contextLists =contextMap.getMatches(request.getPath());
if(contextLists!=null)
{
if(log.isTraceEnabled())log.trace("Contexts at "+request.getPath()+": "+contextLists);
for (int i=0;i _connectionsOpenMax)
_connectionsOpenMax=_connectionsOpen;
}
}
/* ------------------------------------------------------------ */
void statsGotRequest()
{
synchronized(_statsLock)
{
_requestsActive++;
if (_requestsActive > _requestsActiveMax)
_requestsActiveMax=_requestsActive;
}
}
/* ------------------------------------------------------------ */
void statsEndRequest(long duration,boolean ok)
{
synchronized(_statsLock)
{
_requests++;
_requestsActive--;
if (_requestsActive<0)
_requestsActive=0;
if (_requestsActive < _requestsActiveMin)
_requestsActiveMin=_requestsActive;
if (ok)
{
_requestsDurationTotal+=duration;
if (_requestsDurationMin==0 || duration<_requestsDurationMin)
_requestsDurationMin=duration;
if (duration>_requestsDurationMax)
_requestsDurationMax=duration;
}
else
_errors++;
}
}
/* ------------------------------------------------------------ */
void statsCloseConnection(long duration,int requests)
{
synchronized(_statsLock)
{
_connections++;
_connectionsOpen--;
_connectionsDurationTotal+=duration;
if (_connectionsOpen<0)
_connectionsOpen=0;
if (_connectionsOpen<_connectionsOpenMin)
_connectionsOpenMin=_connectionsOpen;
if (_connectionsDurationMin==0 || duration<_connectionsDurationMin)
_connectionsDurationMin=duration;
if (duration>_connectionsDurationMax)
_connectionsDurationMax=duration;
if (_connectionsRequestsMin==0 || requests<_connectionsRequestsMin)
_connectionsRequestsMin=requests;
if (requests>_connectionsRequestsMax)
_connectionsRequestsMax=requests;
}
}
/* ------------------------------------------------------------ */
/** Save the HttpServer
* The server is saved by serialization to the given filename or URL.
*
* @param saveat A file or URL to save the configuration at.
* @exception MalformedURLException
* @exception IOException
*/
public void save(String saveat)
throws MalformedURLException,
IOException
{
Resource resource = Resource.newResource(saveat);
ObjectOutputStream out = new ObjectOutputStream(resource.getOutputStream());
out.writeObject(this);
out.flush();
out.close();
log.info("Saved "+this+" to "+resource);
}
/* ------------------------------------------------------------ */
/** Destroy a stopped server.
* Remove all components and send notifications to all event
* listeners. The HttpServer must be stopped before it can be destroyed.
*/
public void destroy()
{
__servers.remove(this);
if (isStarted())
throw new IllegalStateException("Started");
if (_listeners!=null)
_listeners.clear();
_listeners=null;
if (_virtualHostMap!=null)
_virtualHostMap.clear();
_virtualHostMap=null;
_notFoundContext=null;
super.destroy();
}
/* ------------------------------------------------------------ */
/* ------------------------------------------------------------ */
/** Construct server from command line arguments.
* @param args
*/
public static void main(String[] args)
{
if (args.length==0 || args.length>2)
{
System.err.println
("\nUsage - java HttpServer [:]");
System.err.println
("\nUsage - java HttpServer -r [savefile]");
System.err.println
(" Serves files from '.' directory");
System.err.println
(" Dump handler for not found requests");
System.err.println
(" Default port is 8080");
System.exit(1);
}
try{
if (args.length==1)
{
// Create the server
HttpServer server = new HttpServer();
// Default is no virtual host
String host=null;
HttpContext context = server.getContext(host,"/");
context.setResourceBase(".");
context.addHandler(new ResourceHandler());
context.addHandler(new DumpHandler());
context.addHandler(new NotFoundHandler());
InetAddrPort address = new InetAddrPort(args[0]);
server.addListener(address);
server.start();
}
else
{
Resource resource = Resource.newResource(args[1]);
ObjectInputStream in = new ObjectInputStream(resource.getInputStream());
HttpServer server = (HttpServer)in.readObject();
in.close();
server.start();
}
}
catch (Exception e)
{
log.warn(LogSupport.EXCEPTION,e);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy