You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@locus.apache.org on 2000/04/25 19:54:36 UTC

cvs commit: jakarta-tomcat/src/share/org/apache/tomcat/util CookieTools.java MimeMap.java

costin      00/04/25 10:54:35

  Modified:    src/share/org/apache/tomcat/context AutoSetup.java
                        DefaultCMSetter.java
               src/share/org/apache/tomcat/core Context.java
                        ContextManager.java HttpServletResponseFacade.java
                        RequestImpl.java ResponseImpl.java
               src/share/org/apache/tomcat/request SimpleMapper1.java
               src/share/org/apache/tomcat/service
                        Ajp11ConnectionHandler.java PoolTcpConnector.java
               src/share/org/apache/tomcat/service/connector
                        Ajp12ConnectionHandler.java
               src/share/org/apache/tomcat/service/http
                        HttpConnectionHandler.java HttpRequestAdapter.java
                        HttpResponseAdapter.java
               src/share/org/apache/tomcat/startup Tomcat.java
               src/share/org/apache/tomcat/task ApacheConfig.java
               src/share/org/apache/tomcat/util CookieTools.java
                        MimeMap.java
  Log:
  Initial checkin for virtual host support.
  It doesn't change almost anything in tomcat, so probably the effect
  will be minor for the existing code ( it's mostly an experimental plugin).
  
  Changes:
  - added a "host" property to Context
  - In AutoSetup and ApacheConfig generator - deal only with the
  "default" server. Code to auto-config virtual hosts require discussion,
  apache config with virtual hosts requires more experiments.
  - In DefaultCMSetter - use the vhost in temp name generation
  - In ContextManager - the only "important" change, deprecate getContext(path)
  and all the code that assumed ctx path is a key. The code still works,
  using the default server. After everything is tested and if nobody has
  dependencies we can remove that.
  - In SimpleMapper1 - added the code to map based on ServerName.
  - In Tomcat starter - deal with virtual host definition
  
  Few notes:
  - We can add a VirtualHost object if we really find a need for that.
  It will be only a convenience object, and I feel it's better to not do it
  right now. A ContextGroup is a much better concept - but even for that it's
  better to wait till we have more information on the use cases
  
  - ContextManager remains the "communication center" - it is not involved
  in the details of a Context.
  
  - The support for vhost ( and context groups, or any other notion ) is part
  of the mapper interceptor ( any interceptor that is interested in contextMap)
  
  - I tried to keep everything as simple as possible, and more important to
  be able to replace/shortcut the components if a real web server provides the
  data.
  
  - To use vhosts - replace SimpleMapper with SimpleMapper1.
  
  - SimpleMapper1 is not complete - there is a lot more work on factoring
  out the parsing and matching alghoritm and using efficient data structures.
  The "cache" seems very usefull ( i.e. cache last mapping results ), and it
  seems to be a big difference in using Tree instead of Hashtable.
  Anyway, I think it's much better than SimpleMapper.
  
  - it was a single night of work, there is a lot of space for improvements:-)
  
  Revision  Changes    Path
  1.11      +24 -3     jakarta-tomcat/src/share/org/apache/tomcat/context/AutoSetup.java
  
  Index: AutoSetup.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/context/AutoSetup.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- AutoSetup.java	2000/04/06 21:14:45	1.10
  +++ AutoSetup.java	2000/04/25 17:54:09	1.11
  @@ -80,10 +80,31 @@
    */
   public class AutoSetup extends BaseInterceptor {
       int debug=0;
  +    Hashtable definedContexts=new Hashtable();
       
       public AutoSetup() {
       }
   
  +    /** Take note of the added contexts.
  +     *  We can enhance the auto-setup for virtual hosts too,
  +     *  but it's up to this class how it deals with that and
  +     *  existing contexts. 
  +     */
  +    public void addContext(ContextManager cm, Context ctx)
  +	throws TomcatException
  +    {
  +	if( ctx.getHost()== null ) {
  +	    // this is a context that goes into the default server
  +	    // we care only about the root context for autosetup
  +	    // until we define a pattern for automatic vhost setup.
  +	    definedContexts.put( ctx.getPath(), ctx );
  +	}
  +    }
  +    
  +    /** This will add all contexts to the default host.
  +     *	We need a mechanism ( or convention ) to configure
  +     *  virtual hosts too
  +     */
       public void engineInit(ContextManager cm) throws TomcatException {
   	String home=cm.getHome();
   	File webappD=new File(home + "/webapps");
  @@ -135,7 +156,7 @@
   	    if( path.equals("/ROOT") )
   		path="";
   	    
  -	    if( cm.getContext(path) == null ) {
  +	    if(  definedContexts.get(path) == null ) {
   		// if no explicit set up
   		Context ctx=new Context();
   		ctx.setContextManager( cm );
  @@ -144,10 +165,10 @@
   		// don't assume HOME==TOMCAT_HOME
   		File f=new File( webappD, name);
   		ctx.setDocBase( f.getAbsolutePath() );
  -		ctx.log("Automatic context load docBase=\"" + ctx.getDocBase() + "\"");
  +		if( debug > 0 ) cm.log("AutoSetup " + ctx.toString());
   		cm.addContext(ctx);
   	    } else {
  -		//System.out.println("Already set up: " + path + " " + cm.getContext(path));
  +		//System.out.println("Already set up: " + path + " " + definedContexts.get(path));
   	    }
   	}
       }
  
  
  
  1.29      +5 -1      jakarta-tomcat/src/share/org/apache/tomcat/context/DefaultCMSetter.java
  
  Index: DefaultCMSetter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/context/DefaultCMSetter.java,v
  retrieving revision 1.28
  retrieving revision 1.29
  diff -u -r1.28 -r1.29
  --- DefaultCMSetter.java	2000/03/28 03:28:49	1.28
  +++ DefaultCMSetter.java	2000/04/25 17:54:10	1.29
  @@ -273,7 +273,11 @@
   	StringBuffer sb=new StringBuffer();
   	sb.append(cm.getWorkDir());
   	sb.append(File.separator);
  -	sb.append(cm.getHostName() );
  +	String host=ctx.getHost();
  +	if( host==null ) 
  +	    sb.append(cm.getHostName() );
  +	else
  +	    sb.append( host );
   	sb.append("_").append(cm.getPort());
   	sb.append(URLEncoder.encode( ctx.getPath() ));
   	
  
  
  
  1.81      +30 -2     jakarta-tomcat/src/share/org/apache/tomcat/core/Context.java
  
  Index: Context.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/Context.java,v
  retrieving revision 1.80
  retrieving revision 1.81
  diff -u -r1.80 -r1.81
  --- Context.java	2000/04/21 20:45:02	1.80
  +++ Context.java	2000/04/25 17:54:12	1.81
  @@ -147,6 +147,8 @@
       int debug=0;
       // are servlets allowed to access internal objects? 
       boolean trusted=false;
  +    String vhost=null;
  +    Vector vhostAliases=new Vector();
       
       public Context() {
   	//	System.out.println("New Context ");
  @@ -629,7 +631,7 @@
   	if( msg.startsWith( "<l:" ))
   	    contextM.doLog( msg, t );
   	else
  -	    contextM.doLog("Context log: path=\"" + path  + "\" " + msg, t);
  +	    contextM.doLog(this.toString() + " " + msg, t);
       }
   
       boolean firstLog = true;
  @@ -656,7 +658,7 @@
       }
   
       public String toString() {
  -	return "Ctx(" + path + "," + getDocBase() + ")";
  +	return "Ctx( " + (vhost==null ? "" : vhost + ":" )  +  path +  " )";
       }
   
       // -------------------- Facade methods --------------------
  @@ -763,6 +765,7 @@
   	}
   	// absolute path
   	Request lr=contextM.createRequest( path );
  +	if( vhost != null ) lr.setServerName( vhost );
   	getContextManager().processRequest(lr);
           return lr.getContext();
       }
  @@ -1036,4 +1039,29 @@
   	return trusted;
       }
   
  +    /** Make this context visible as part of a virtual host
  +     */
  +    public void setHost( String h ) {
  +	vhost=h;
  +    }
  +
  +    /** Return the virtual host name, or null if we are in the
  +	default context
  +    */
  +    public String getHost() {
  +	return vhost;
  +    }
  +    
  +    /** Virtual host support - this context will be part of 
  +     *  a virtual host with the specified name. You should
  +     *  set all the aliases. XXX Not implemented
  +     */
  +    public void addHostAlias( String alias ) {
  +	vhostAliases.addElement( alias );
  +    }
  +
  +    public Enumeration getHostAliases() {
  +	return vhostAliases.elements();
  +    }
  +    
   }
  
  
  
  1.74      +58 -15    jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java
  
  Index: ContextManager.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ContextManager.java,v
  retrieving revision 1.73
  retrieving revision 1.74
  diff -u -r1.73 -r1.74
  --- ContextManager.java	2000/04/21 20:45:02	1.73
  +++ ContextManager.java	2000/04/25 17:54:13	1.74
  @@ -100,8 +100,13 @@
       /**
        * The set of Contexts associated with this ContextManager,
        * keyed by context paths.
  +     * @deprecated - the server shouldn't make any assumptions about
  +     *  the key.
        */
       private Hashtable contexts = new Hashtable();
  +    /** Contexts managed by this server
  +     */
  +    private Vector contextsV=new Vector();
   
       public static final String DEFAULT_HOSTNAME="localhost";
       public static final int DEFAULT_PORT=8080;
  @@ -175,17 +180,26 @@
       
       /**
        * Get the names of all the contexts in this server.
  +     * @deprecated Path is not "unique key".
        */
       public Enumeration getContextNames() {
           return contexts.keys();
       }
   
  +    /** Return the list of contexts managed by this server
  +     */
  +    public Enumeration getContexts() {
  +	return contextsV.elements();
  +    }
  +    
       /** Init() is called after the context manager is set up
        *  and configured. 
        */
       public void init()  throws TomcatException {
   	String cp=System.getProperty( "java.class.path");
  -	log( "Starting tomcat install=\"" + getTomcatHome() + "\" home=\"" + home + "\" classPath=\"" + cp + "\"");
  +	log( "Tomcat install = " + getTomcatHome());
  +	log( "Tomcat home = " + home);
  +	if(debug>0 ) log( "Tomcat classpath = " +  cp );
   	//	long time=System.currentTimeMillis();
   	ContextInterceptor cI[]=getContextInterceptors();
   	for( int i=0; i< cI.length; i++ ) {
  @@ -193,16 +207,16 @@
   	}
   	
       	// init contexts
  -	Enumeration enum = getContextNames();
  +	Enumeration enum = getContexts();
   	Context context=null;
   	while (enum.hasMoreElements()) {
  -	    context = getContext((String)enum.nextElement());
  +	    context = (Context)enum.nextElement();
   	    try {
   		initContext( context );
   	    } catch (TomcatException ex ) {
   		if( context!=null ) {
   		    log( "ERROR initializing " + context.toString() );
  -		    removeContext( context.getPath() );	    
  +		    removeContext( context  );	    
   		    Throwable ex1=ex.getRootCause();
   		    if( ex1!=null ) ex.printStackTrace();
   		}
  @@ -273,8 +287,13 @@
        * no such context.
        *
        * @param name Name of the requested context
  +     * @deprecated Use an external iterator to find the context that
  +     *  matches your conditions.
  +     *
        */
       public Context getContext(String name) {
  +	// System.out.println("Using deprecated getContext");
  +	//	/*DEBUG*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();}
   	return (Context)contexts.get(name);
       }
       
  @@ -287,31 +306,36 @@
   	// Make sure context knows about its manager.
   	ctx.setContextManager( this );
   
  -	// it will replace existing context - it's better than  IllegalStateException.
  -	String path=ctx.getPath();
  -	if( getContext( path ) != null ) {
  -	    if(debug>0) log("Warning: replacing context for " + path);
  -	    removeContext(path);
  -	}
  +	// If the context already exist - the interceptors need
  +	// to deal with that ( either replace or throw an exception ).
  +
  +	// The mapping alghoritm may use more than path and host -
  +	// if not now, then in future.
   
   	ContextInterceptor cI[]=getContextInterceptors();
   	for( int i=0; i< cI.length; i++ ) {
   	    cI[i].addContext( this, ctx );
   	}
  -	
  -	ctx.log("Adding context path=\"" +  ctx.getPath() + "\"  docBase=\"" + ctx.getDocBase() + "\"");
  +
  +	String vhost=ctx.getHost();
  +	log("Adding context " +  ctx.toString());
   
  -	contexts.put( path, ctx );
  +	// XXX temporary workaround for the old SimpleMapper -
  +	// This code will be removed as soon as the new mapper is stable.
  +	if( vhost ==null ) // the old mapper will support only "default" server
  +	    contexts.put( ctx.getPath(), ctx );
  +	contextsV.addElement( ctx );
       }
       
       /**
        * Shut down and removes a context from service.
        *
        * @param name Name of the Context to be removed
  +     * @deprecated Use removeContext( Context ).
        */
       public void removeContext(String name) throws TomcatException {
   	Context context = (Context)contexts.get(name);
  -	log( "Removing context path=\"" + context.getPath() + "\" ");
  +	log( "Removing context " + context.toString());
   
   	ContextInterceptor cI[]=getContextInterceptors();
   	for( int i=0; i< cI.length; i++ ) {
  @@ -324,6 +348,22 @@
   	}
       }
   
  +    /** Shut down and removes a context from service
  +     */
  +    public void removeContext( Context context ) throws TomcatException {
  +	if( context==null ) return;
  +	
  +	log( "Removing context " + context.toString());
  +
  +	ContextInterceptor cI[]=getContextInterceptors();
  +	for( int i=0; i< cI.length; i++ ) {
  +	    cI[i].removeContext( this, context );
  +	}
  +
  +	shutdownContext( context );
  +	contextsV.removeElement(context);
  +    }
  +    
       public void addContainer( Container container )
       	throws TomcatException
       {
  @@ -764,7 +804,10 @@
   	}
   
   	if( debug >4 ) log("createRequest " + origPath + " " + urlPath  );
  -	return createRequest( urlPath );
  +	Request req= createRequest( urlPath );
  +	String host=ctx.getHost();
  +	if( host != null) req.setServerName( host );
  +	return req;
       }
   
       /** Create a new sub-request, deal with query string
  
  
  
  1.13      +4 -5      jakarta-tomcat/src/share/org/apache/tomcat/core/HttpServletResponseFacade.java
  
  Index: HttpServletResponseFacade.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/HttpServletResponseFacade.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- HttpServletResponseFacade.java	2000/04/18 23:04:29	1.12
  +++ HttpServletResponseFacade.java	2000/04/25 17:54:13	1.13
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/HttpServletResponseFacade.java,v 1.12 2000/04/18 23:04:29 costin Exp $
  - * $Revision: 1.12 $
  - * $Date: 2000/04/18 23:04:29 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/HttpServletResponseFacade.java,v 1.13 2000/04/25 17:54:13 costin Exp $
  + * $Revision: 1.13 $
  + * $Date: 2000/04/25 17:54:13 $
    *
    * ====================================================================
    *
  @@ -82,8 +82,7 @@
   public class HttpServletResponseFacade
       implements HttpServletResponse
   {
  -
  -    private StringManager sm =
  +    private static StringManager sm =
           StringManager.getManager(Constants.Package);
       private Response response;
   
  
  
  
  1.30      +5 -5      jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java
  
  Index: RequestImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v
  retrieving revision 1.29
  retrieving revision 1.30
  diff -u -r1.29 -r1.30
  --- RequestImpl.java	2000/04/21 20:45:03	1.29
  +++ RequestImpl.java	2000/04/25 17:54:14	1.30
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v 1.29 2000/04/21 20:45:03 costin Exp $
  - * $Revision: 1.29 $
  - * $Date: 2000/04/21 20:45:03 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/RequestImpl.java,v 1.30 2000/04/25 17:54:14 costin Exp $
  + * $Revision: 1.30 $
  + * $Date: 2000/04/25 17:54:14 $
    *
    * ====================================================================
    *
  @@ -93,7 +93,7 @@
       protected String queryString;
   
      //  RequestAdapterImpl Hints
  -    protected String serverName;
  +    protected String serverName=null;
       protected Vector cookies = new Vector();
   
       protected String contextPath;
  @@ -610,7 +610,7 @@
   	queryString=null;
   	protocol="HTTP/1.0";
   	headers.clear(); // XXX use recycle pattern
  -	serverName="localhost";
  +	serverName=null;
   	serverPort=8080;
   	pathTranslated=null;
   	pathInfo=null;
  
  
  
  1.23      +13 -6     jakarta-tomcat/src/share/org/apache/tomcat/core/ResponseImpl.java
  
  Index: ResponseImpl.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ResponseImpl.java,v
  retrieving revision 1.22
  retrieving revision 1.23
  diff -u -r1.22 -r1.23
  --- ResponseImpl.java	2000/04/21 20:45:03	1.22
  +++ ResponseImpl.java	2000/04/25 17:54:15	1.23
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ResponseImpl.java,v 1.22 2000/04/21 20:45:03 costin Exp $
  - * $Revision: 1.22 $
  - * $Date: 2000/04/21 20:45:03 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/core/ResponseImpl.java,v 1.23 2000/04/25 17:54:15 costin Exp $
  + * $Revision: 1.23 $
  + * $Date: 2000/04/25 17:54:15 $
    *
    * ====================================================================
    *
  @@ -149,13 +149,13 @@
       }
   
       public void recycle() {
  -	userCookies.removeAllElements();
  +	userCookies.removeAllElements(); // XXX reuse !!!
   	contentType = Constants.DEFAULT_CONTENT_TYPE;
  +	contentLanguage = null;
           locale = new Locale(Constants.LOCALE_DEFAULT, "");
   	characterEncoding = Constants.DEFAULT_CHAR_ENCODING;
   	contentLength = -1;
   	status = 200;
  -	headers.clear();
   	usingWriter = false;
   	usingStream = false;
   	sessionId=null;
  @@ -166,6 +166,13 @@
   	// adapter
   	body.setLength(0);
   	if( out != null ) out.recycle();
  +
  +
  +	out.recycle(); //=new BufferedServletOutputStream();
  +	//	out.setResponse(this);
  +
  +	headers.clear();
  +	//headers = new MimeHeaders();
       }
   
       public void finish() throws IOException {
  @@ -487,5 +494,5 @@
       public static String getMessage( int status ) {
   	return sm.getString("sc."+ status);
       }
  -    
  +
   }
  
  
  
  1.2       +39 -16    jakarta-tomcat/src/share/org/apache/tomcat/request/SimpleMapper1.java
  
  Index: SimpleMapper1.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/request/SimpleMapper1.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- SimpleMapper1.java	2000/04/22 02:01:00	1.1
  +++ SimpleMapper1.java	2000/04/25 17:54:19	1.2
  @@ -106,6 +106,7 @@
       int debug=0;
       ContextManager cm;
       Mappings map;
  +    Hashtable vhostMaps=new Hashtable();
       int ctExtMapNote=-1;
       boolean mapCacheEnabled=false;
       
  @@ -190,7 +191,6 @@
        */
       public void addContext( ContextManager cm, Context ctx ) throws TomcatException
       {
  -	if(debug>0) log( "Adding to maps " + ctx);
   	// find all the mappings that are declared in context,
   	// and register them.
   	
  @@ -198,8 +198,19 @@
   	// we have pre-set mappings - not very common 
   	// or tested. Normal operation is to set up tomcat
   	// and the interceptors and then add the contexts.
  +	String vhost=ctx.getHost();
  +	if( vhost == null ) {
  +	    map.prefixMappedServlets.put( ctx.getPath(), ctx.getContainer());
  +        }  else {
  +	    Mappings vmap=(Mappings)vhostMaps.get( vhost );
  +	    if( vmap == null ) {
  +		vmap=new Mappings();
  +		vhostMaps.put( vhost, vmap );
  +	    }
  +	    vmap.prefixMappedServlets.put( ctx.getPath(), ctx.getContainer());
  +	}
   
  -	map.prefixMappedServlets.put( ctx.getPath(), ctx.getContainer());
  +	if(debug>0) log( "SM: default map " + vhost +":" + ctx.getPath() + " -> " + ctx.getContainer() );
   	
   	Enumeration ctE=ctx.getContainers();
   	while( ctE.hasMoreElements() ) {
  @@ -239,20 +250,24 @@
   	throws TomcatException
       {
   	Context ctx=ct.getContext();
  +	String vhost=ctx.getHost();
   	String path=ct.getPath();
   	String ctxP=ctx.getPath();
   
  -	// 	if( ct.getHandler() != null )
  -	// 	    mtable=contextPaths;
  -
  -	if(debug>0) log("SM: Add mapping/container " + path + " " + ctx.getDebug() + " " + ctxP + " " +
  -			    ct.getHandler() + " " + ct.getRoles());
  +	Mappings myMap;
  +	if( vhost==null )
  +	    myMap=map; // global contexs
  +	else
  +	    myMap=(Mappings)vhostMaps.get( vhost );
  +	// assert myMap!= null ( we just added the context, so the map is there
   
  +	String vhostS=( vhost==null )? "": vhost;
  +	
   	switch( ct.getMapType() ) {
   	case Container.PREFIX_MAP:
   	    // cut /* !
  -	    map.prefixMappedServlets.put( ctxP + path.substring( 0, path.length()-2 ), ct);
  -	    if( debug>0 ) log("SM: Adding Prefix Map " + ctxP + path + " -> " + ct + " " );
  +	    myMap.prefixMappedServlets.put( ctxP + path.substring( 0, path.length()-2 ), ct);
  +	    if( debug>0 ) log("SM: prefix map " + vhostS + ":" +  ctxP + path + " -> " + ct + " " );
   	    break;
   	case Container.EXTENSION_MAP:
   	    // Add it per/defaultContainer - as spec require ( it may also be
  @@ -268,11 +283,11 @@
   	    }
   	    // add it to the Container local maps
   	    eM.put( path.substring( 1 ), ct );
  -	    if(debug>0) log( "Add Extension Map " + ctxP + "/" + path + " " + ct + " " );
  +	    if(debug>0) log( "SM: extension map " + ctxP + "/" + path + " " + ct + " " );
   	    break;
   	case Container.PATH_MAP:
  -	    map.prefixMappedServlets.put( ctxP + path, ct);
  -	    if( debug>0 ) log("SM: Adding Exact Map " + ctxP + path + " -> " + ct + " " );
  +	    myMap.prefixMappedServlets.put( ctxP + path, ct);
  +	    if( debug>0 ) log("SM: exact map " + vhostS + ":" + ctxP + path + " -> " + ct + " " );
   	    break;
   	}
       }
  @@ -308,6 +323,13 @@
   	    path=path.substring(0, foundAt);  
   	}
   
  +	String host=req.getServerName();
  +	cm.log("Host = " + host);
  +
  +	// try to find a vhost with this name
  +	Mappings myMap=(Mappings)vhostMaps.get( host );
  +	if( myMap==null ) myMap = map; // default server
  +	
   	try {
   
   	Context ctx = null;
  @@ -316,7 +338,7 @@
   	boolean cached=false;
   	
   	if( mapCacheEnabled ) {
  -	    container=(Container)getCachedResult( path );
  +	    container=(Container)getCachedResult( host + ":" + path );//XXX remove strings!
   	    if( container != null ) {
   		cached=true;
   		if(debug>0) log( "CM: cache hit " + path);
  @@ -324,7 +346,7 @@
   	}
   	
   	if( ! cached )
  -	    container=(Container)map.getLongestPrefixMatch(  path );
  +	    container=(Container)myMap.getLongestPrefixMatch(  path );
   	
   	if( container == null ) throw new RuntimeException( "Assertion failed - container==null");
   	if( container.getHandler() == null ) throw new RuntimeException( "Assertion failed - container.handler==null");
  @@ -354,7 +376,7 @@
   	}
   	
   	if( mapCacheEnabled && ! cached ) {
  -	    addCachedResult( path, container );
  +	    addCachedResult( host + ":" + path, container );//XXX remove strings!
   	}
   	    
   	if(debug>0) log("SM: After mapping " + req + " " + req.getWrapper());
  @@ -411,6 +433,7 @@
   	String ctxP=ctx.getPath();
   	String path = req.getPathInfo(); // we haven't matched any prefix,
   	// we check path Info
  +	if( path == null ) return null;
   	String extension=StringUtil.getExtension( path );
   
   	if(debug>0) cm.log("SM: Extension match " + ctxP +  " " + path + " " + extension );
  @@ -515,7 +538,7 @@
   	//if( s.endsWith( "/" ))
   	//  s=removeLast(s);
   	
  -	while (s.length() > 0) {
  +	while (s.length() >= 0) {
   	    //if(debug>8) context.log( "Prefix: " + s  );
   	    container = (Container)prefixMappedServlets.get(s);
   	    
  
  
  
  1.17      +6 -9      jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java
  
  Index: Ajp11ConnectionHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v
  retrieving revision 1.16
  retrieving revision 1.17
  diff -u -r1.16 -r1.17
  --- Ajp11ConnectionHandler.java	2000/02/17 07:52:21	1.16
  +++ Ajp11ConnectionHandler.java	2000/04/25 17:54:20	1.17
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v 1.16 2000/02/17 07:52:21 costin Exp $
  - * $Revision: 1.16 $
  - * $Date: 2000/02/17 07:52:21 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/Ajp11ConnectionHandler.java,v 1.17 2000/04/25 17:54:20 costin Exp $
  + * $Revision: 1.17 $
  + * $Date: 2000/04/25 17:54:20 $
    *
    * ====================================================================
    *
  @@ -165,7 +165,7 @@
   
   	Hashtable env_vars=new Hashtable();
   
  -	Ajp11.readAJPData(sin, env_vars, headers);
  +	readAJPData(sin, env_vars);
   	
   	// equiv of readRequestLine ( firsts line of the Request )
   	method= (String)env_vars.get("REQUEST_METHOD");
  @@ -213,16 +213,13 @@
   	//moreRequests = false;	
       }    
   
  -}
  -
  -
  -class Ajp11 {
  +    // Ajp11 protocol implementation 
       public static final int CH_REQUEST_DATA=1;
   
       // UTF8 is a strict superset of ASCII.
       final static String CHARSET = "UTF8";
   
  -    public static void readAJPData(InputStream in, Hashtable env_vars, MimeHeaders headers ) throws IOException {
  +    void readAJPData(InputStream in, Hashtable env_vars ) throws IOException {
   	byte id = 0;
           int index = 0;
           String token1 = null;
  
  
  
  1.3       +7 -4      jakarta-tomcat/src/share/org/apache/tomcat/service/PoolTcpConnector.java
  
  Index: PoolTcpConnector.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/PoolTcpConnector.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- PoolTcpConnector.java	2000/03/20 19:34:10	1.2
  +++ PoolTcpConnector.java	2000/04/25 17:54:21	1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/PoolTcpConnector.java,v 1.2 2000/03/20 19:34:10 costin Exp $
  - * $Revision: 1.2 $
  - * $Date: 2000/03/20 19:34:10 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/PoolTcpConnector.java,v 1.3 2000/04/25 17:54:21 costin Exp $
  + * $Revision: 1.3 $
  + * $Date: 2000/04/25 17:54:21 $
    *
    * ====================================================================
    *
  @@ -169,7 +169,10 @@
   	}
   	ep.setConnectionHandler( con );
   	ep.startEndpoint();
  -	System.out.println("Starting tcp endpoint on " + port + " with " + con.getClass().getName());
  +	String classN=con.getClass().getName();
  +	int lidot=classN.lastIndexOf( "." );
  +	if( lidot >0 ) classN=classN.substring( lidot + 1 );
  +	System.out.println("Starting " + classN + " on " + port);
       }
   
       public void stop() throws Exception {
  
  
  
  1.24      +3 -1      jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Ajp12ConnectionHandler.java
  
  Index: Ajp12ConnectionHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/connector/Ajp12ConnectionHandler.java,v
  retrieving revision 1.23
  retrieving revision 1.24
  diff -u -r1.23 -r1.24
  --- Ajp12ConnectionHandler.java	2000/04/24 23:06:05	1.23
  +++ Ajp12ConnectionHandler.java	2000/04/25 17:54:23	1.24
  @@ -164,7 +164,7 @@
   	    }
   
   	    contextM.service( reqA, resA );
  -	    resA.finish();
  +	    //resA.finish(); // is part of contextM !
   	    socket.close();
   	} catch (Exception e) {
               // XXX
  @@ -496,9 +496,11 @@
       /** Override setStatus
        */
       protected void sendStatus( int status, String message)  throws IOException {
  +	///*DEBUG*/ try {throw new Exception(); } catch(Exception ex) {ex.printStackTrace();}
   	statusSB.setLength(0);
   	statusSB.append("Status: " ).append( status ).append(" ").append(message).append("\r\n");
   	sout.write(statusSB.toString().getBytes());
  +	statusSB.setLength(0);
       }
   }
   
  
  
  
  1.22      +7 -6      jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpConnectionHandler.java
  
  Index: HttpConnectionHandler.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpConnectionHandler.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- HttpConnectionHandler.java	2000/04/21 20:45:07	1.21
  +++ HttpConnectionHandler.java	2000/04/25 17:54:25	1.22
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpConnectionHandler.java,v 1.21 2000/04/21 20:45:07 costin Exp $
  - * $Revision: 1.21 $
  - * $Date: 2000/04/21 20:45:07 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpConnectionHandler.java,v 1.22 2000/04/25 17:54:25 costin Exp $
  + * $Revision: 1.22 $
  + * $Date: 2000/04/25 17:54:25 $
    *
    * ====================================================================
    *
  @@ -92,14 +92,14 @@
   	this.contextM=contextM;
       }
   
  -    public Object[] init( ) {
  -	Object thData[]=new Object[2];
  +    public Object[] init() {
  +	Object thData[]=new Object[3];
   	HttpRequestAdapter reqA=new HttpRequestAdapter();
   	HttpResponseAdapter resA=new HttpResponseAdapter();
   	contextM.initRequest( reqA, resA );
   	thData[0]=reqA;
   	thData[1]=resA;
  -	
  +	thData[2]=null;
   	return  thData;
       }
   
  @@ -131,6 +131,7 @@
   		resA=(HttpResponseAdapter)thData[1];
   		if( reqA!=null ) reqA.recycle();
   		if( resA!=null ) resA.recycle();
  +		//		System.out.println("Request ID " + thData[2]);
   	    }
   	    if( reqA==null || resA==null ) {
   		reqA=new HttpRequestAdapter();
  
  
  
  1.11      +6 -5      jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpRequestAdapter.java
  
  Index: HttpRequestAdapter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpRequestAdapter.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- HttpRequestAdapter.java	2000/04/21 20:45:07	1.10
  +++ HttpRequestAdapter.java	2000/04/25 17:54:26	1.11
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpRequestAdapter.java,v 1.10 2000/04/21 20:45:07 costin Exp $
  - * $Revision: 1.10 $
  - * $Date: 2000/04/21 20:45:07 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpRequestAdapter.java,v 1.11 2000/04/25 17:54:26 costin Exp $
  + * $Revision: 1.11 $
  + * $Date: 2000/04/25 17:54:26 $
    *
    * ====================================================================
    *
  @@ -147,7 +147,7 @@
   
       public String getServerName() {
   	if(serverName!=null) return serverName;
  -
  +	
   	// XXX Move to interceptor!!!
   	String hostHeader = this.getHeader("host");
   	if (hostHeader != null) {
  @@ -177,12 +177,13 @@
   	return socket.getInetAddress().getHostName();
       }    
       
  -    public void processRequestLine(Response response, byte bug[], int start, int count)
  +    public void processRequestLine(Response response, byte buf[], int start, int count)
   	throws IOException
       {
   
   	String line=new String(buf, 0, count, Constants.CharacterEncoding.Default);
           String buffer = line.trim();
  +
   	int firstDelim = buffer.indexOf(' ');
   	int lastDelim = buffer.lastIndexOf(' ');
   	// default - set it to HTTP/0.9 or null if we can parse the request
  
  
  
  1.8       +4 -4      jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java
  
  Index: HttpResponseAdapter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- HttpResponseAdapter.java	2000/02/16 17:13:24	1.7
  +++ HttpResponseAdapter.java	2000/04/25 17:54:26	1.8
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java,v 1.7 2000/02/16 17:13:24 costin Exp $
  - * $Revision: 1.7 $
  - * $Date: 2000/02/16 17:13:24 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/service/http/HttpResponseAdapter.java,v 1.8 2000/04/25 17:54:26 costin Exp $
  + * $Revision: 1.8 $
  + * $Date: 2000/04/25 17:54:26 $
    *
    * ====================================================================
    *
  @@ -94,7 +94,7 @@
       }
   
       public void recycle() {
  -	sout=null;
  +	super.recycle();
   	statusSB.setLength(0);
   	headersSB.setLength(0);
       }
  
  
  
  1.22      +66 -0     jakarta-tomcat/src/share/org/apache/tomcat/startup/Tomcat.java
  
  Index: Tomcat.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/startup/Tomcat.java,v
  retrieving revision 1.21
  retrieving revision 1.22
  diff -u -r1.21 -r1.22
  --- Tomcat.java	2000/04/04 00:58:19	1.21
  +++ Tomcat.java	2000/04/25 17:54:29	1.22
  @@ -10,6 +10,7 @@
   import org.apache.tomcat.util.*;
   import org.apache.tomcat.util.xml.*;
   import org.apache.tomcat.core.*;
  +import org.xml.sax.*;
   
   // Used to stop tomcat
   import org.apache.tomcat.service.TcpEndpointConnector;
  @@ -59,11 +60,52 @@
   	xh.addRule( "ContextManager/RequestInterceptor", xh.addChild( "addRequestInterceptor",
   								      "org.apache.tomcat.core.RequestInterceptor" ) );
   
  +	// Default host
    	xh.addRule( "ContextManager/Context", xh.objectCreate("org.apache.tomcat.core.Context"));
   	xh.addRule( "ContextManager/Context", xh.setParent( "setContextManager") );
   	xh.addRule( "ContextManager/Context", xh.setProperties() );
   	xh.addRule( "ContextManager/Context", xh.addChild( "addContext", null ) );
   
  +	// Virtual host support.
  +	// Push a host object on the stack
  + 	xh.addRule( "ContextManager/Host", new XmlAction() {
  +		public void start( SaxContext ctx) throws Exception {
  +		    Stack st=ctx.getObjectStack();
  +		    // get attributes 
  +		    int top=ctx.getTagCount()-1;
  +		    AttributeList attributes = ctx.getAttributeList( top );
  +
  +		    // get CM
  +		    ContextManager cm=(ContextManager)st.peek();
  +
  +		    // construct virtual host config helper
  +		    HostConfig hc=new HostConfig(cm);
  +
  +		    // set the host name
  +		    hc.setName( attributes.getValue("name")); 
  +		    st.push( hc );
  +		}
  +		public void cleanup( SaxContext ctx) {
  +		    Stack st=ctx.getObjectStack();
  +		    Object o=st.pop();
  +		}
  +	    });
  +	xh.addRule( "ContextManager/Host", xh.setProperties());
  +	
  + 	xh.addRule( "ContextManager/Host/Context", xh.objectCreate("org.apache.tomcat.core.Context"));
  +	xh.addRule( "ContextManager/Host/Context", xh.setProperties() );
  +	xh.addRule( "ContextManager/Host/Context", new XmlAction() {
  +		public void end( SaxContext ctx) throws Exception {
  +		    Stack st=ctx.getObjectStack();
  +		    
  +		    Context tcCtx=(Context)st.pop(); // get the Context
  +		    HostConfig hc=(HostConfig)st.peek();
  +		    st.push( tcCtx ); // put back the context, to be cleaned up corectly
  +
  +		    hc.addContext( tcCtx );
  +		}
  +	    });
  +
       }
   
       void setConnectorHelper( XmlMapper xh ) {
  @@ -255,3 +297,27 @@
   
   }
   
  +
  +class HostConfig {
  +    ContextManager cm;
  +    String hostName;
  +    
  +    public HostConfig(ContextManager cm) {
  +	this.cm=cm;
  +    }
  +
  +    public void setName( String name ) {
  +	hostName=name;
  +    }
  +    
  +    public void addContext( Context ctx ) {
  +	try {
  +	    ctx.setContextManager( cm );
  +	    ctx.setHost( hostName );
  +	    cm.addContext( ctx );
  +	} catch(Exception ex ) {
  +	    ex.printStackTrace();
  +	}
  +    }
  +}
  +    
  
  
  
  1.8       +12 -4     jakarta-tomcat/src/share/org/apache/tomcat/task/ApacheConfig.java
  
  Index: ApacheConfig.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/task/ApacheConfig.java,v
  retrieving revision 1.7
  retrieving revision 1.8
  diff -u -r1.7 -r1.8
  --- ApacheConfig.java	2000/04/25 00:38:11	1.7
  +++ ApacheConfig.java	2000/04/25 17:54:31	1.8
  @@ -116,11 +116,19 @@
   	    pw.println();
   
   	    // Set up contexts 
  -	    
  -	    Enumeration enum = cm.getContextNames();
  +	    // XXX deal with Virtual host configuration !!!!
  +	    Enumeration enum = cm.getContexts();
   	    while (enum.hasMoreElements()) {
  -		String path=(String)enum.nextElement();
  -		Context context = cm.getContext(path);
  +		Context context = (Context)enum.nextElement();
  +		String path=context.getPath();
  +		String vhost=context.getHost();
  +
  +		if( vhost != null ) {
  +		    // Generate Apache VirtualHost section for this host
  +		    // You'll have to do it manually right now
  +		    // XXX 
  +		    continue;
  +		} 
   		if( path.length() > 1) {
   
   		    // It's not the root context
  
  
  
  1.4       +8 -6      jakarta-tomcat/src/share/org/apache/tomcat/util/CookieTools.java
  
  Index: CookieTools.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/CookieTools.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- CookieTools.java	2000/04/06 22:31:04	1.3
  +++ CookieTools.java	2000/04/25 17:54:32	1.4
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/CookieTools.java,v 1.3 2000/04/06 22:31:04 craigmcc Exp $
  - * $Revision: 1.3 $
  - * $Date: 2000/04/06 22:31:04 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/CookieTools.java,v 1.4 2000/04/25 17:54:32 costin Exp $
  + * $Revision: 1.4 $
  + * $Date: 2000/04/25 17:54:32 $
    *
    * ====================================================================
    *
  @@ -86,9 +86,13 @@
               return "Set-Cookie";
           }
       }
  -
       public static String getCookieHeaderValue(Cookie cookie) {
           StringBuffer buf = new StringBuffer();
  +	getCookieHeaderValue( cookie, buf );
  +	return buf.toString();
  +    }
  +    
  +    public static void getCookieHeaderValue(Cookie cookie, StringBuffer buf) {
           int version = cookie.getVersion();
   
           // this part is the same for all cookies
  @@ -138,8 +142,6 @@
   	if (cookie.getSecure()) {
   	  buf.append (";Secure");
   	}
  -
  -	return buf.toString();
       }
   
       static void maybeQuote (int version, StringBuffer buf,
  
  
  
  1.3       +4 -4      jakarta-tomcat/src/share/org/apache/tomcat/util/MimeMap.java
  
  Index: MimeMap.java
  ===================================================================
  RCS file: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MimeMap.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- MimeMap.java	2000/02/10 22:28:24	1.2
  +++ MimeMap.java	2000/04/25 17:54:33	1.3
  @@ -1,7 +1,7 @@
   /*
  - * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MimeMap.java,v 1.2 2000/02/10 22:28:24 costin Exp $
  - * $Revision: 1.2 $
  - * $Date: 2000/02/10 22:28:24 $
  + * $Header: /home/cvs/jakarta-tomcat/src/share/org/apache/tomcat/util/MimeMap.java,v 1.3 2000/04/25 17:54:33 costin Exp $
  + * $Revision: 1.3 $
  + * $Date: 2000/04/25 17:54:33 $
    *
    * ====================================================================
    *
  @@ -121,7 +121,7 @@
       public String getContentTypeFor(String fileName) {
   	String extn=getExtension( fileName );
           if (extn!=null) {
  -            return getContentType(extn.toLowerCase());
  +            return getContentType(extn);
           } else {
               // no extension, no content type
               return null;