// VirtualHostResource.java
// $Id: VirtualHostResource.java,v 1.9 1997/03/27 09:56:23 abaird Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.resources;

import java.util.*;
import java.io.*;

import w3c.tools.store.*;
import w3c.util.*;
import w3c.jigsaw.http.*;

public class VirtualHostResource extends StoreContainer {
    /**
     * Attribute index - The default root (for unknown hosts)
     */
    protected static int ATTR_FOLLOWUP = -1;

    static {
	Class     c = null;
	Attribute a = null;

	try {
	    c = Class.forName("w3c.jigsaw.resources.VirtualHostResource");
	} catch (Exception ex) {
	    ex.printStackTrace();
	    System.exit(1);
	}
	// Register our default root:
	a = new StringAttribute("followup"
				, null
				, Attribute.EDITABLE);
	ATTR_FOLLOWUP = AttributeRegistry.registerAttribute(c, a);
    }

    protected HTTPResource followup = null;
    protected Hashtable    defs     = null;

    /**
     * Create a default resource for that container.
     * This method will just fail, since they are no there is no specific
     * resource class to be attached to that class of resources.
     * @param name The name of the resource to be created.
     * @return Always <strong>null</strong>.
     */

    public HTTPResource createDefaultResource(String name) {
	return null;
    }

    /**
     * Register a new host within that container.
     * The host identifier (which matches the host name) is case lowered, so
     * that we can perform case insensitive comparison of host names.
     * @param id The name of the new host (includes port number).
     * @param resource The resource for handling that host (un-initialized).
     * @param defs Default attribute values.
     */

    public synchronized void registerResource(String id
					      , Resource resource
					      , Hashtable defs) {
	super.registerResource(id.toLowerCase(), resource, defs);
    }

    /**
     * Resolve the given name in our store.
     * @param name The name to resolve.
     */

    protected synchronized HTTPResource lookupStore(String host) 
	throws InvalidResourceException
    {
	ResourceStore store = getResourceStore();
	// Overide the host URL, now:
	defs.put("url", "http://"+host);
	return super.lookupStore(host, defs);
    }

    /**
     * Get the name of the resource used as a followup.
     * @return A String giving the name of the resource to be used as the
     * default.
     */

    public String getFollowup() {
	return getString(ATTR_FOLLOWUP, null);
    }

    /**
     * Lookup the followup resource.
     * @return The loaded resource for the current followup.
     */

    public synchronized HTTPResource lookupFollowup() {
	if ( followup == null ) {
	    String name  = getFollowup();
	    if ( name != null ) 
		followup = getServer().loadRoot(name);
	    if ( followup == null ) {
		getServer().errlog(getIdentifier()
				   + "[" + getClass().getName() + "]: "
				   + "unable to restore \"" + name + "\" "
				   + " from root store.");
	    }
	}
	return followup;
    }

    /**
     * Lookup the virtual host resource to continue lookup.
     * This is one of the neatest piece of code that Jigsaw allows you to 
     * write.
     */

    public boolean lookup(LookupState ls, LookupResult lr) 
	throws HTTPException
    {
	// If this is an internal lookup, it's pretty easy:
	if ( ls.isInternal() ) {
	    return super.lookup(ls, lr);
	}
	// Try to lookup on the host header:
	HTTPResource vroot = null;
	Request r = ls.getRequest();
	if ( r != null ) {
	    String  host = r.getHost();
	    if ( host != null ) {
		try {
		    vroot = lookupStore(host.toLowerCase());
		} catch (InvalidResourceException ex) {
		    vroot = null;
		}
	    }
	}
	if ( vroot == null )
	    vroot  = lookupFollowup();
	// Check for what we got:
	return (vroot == null) ? super.lookup(ls, lr) : vroot.lookup(ls, lr);
    }

    public Reply perform(Request request) 
	throws HTTPException, ClientException
    {
	HTTPResource followup = lookupFollowup();
	if ( followup != null )
	    return followup.perform(request);
	else
	    return super.perform(request);
    }

    public void initialize(Object values[]) {
	super.initialize(values);
	// Initialize default attributes for our vritual resources:
	HTTPResource parent = getParent();
	defs = new Hashtable(11);
	defs.put("resource-store", getResourceStore());
	defs.put("context", getContext());
	defs.put("parent", this);
	if ( parent != null ) {
	    defs.put("url", parent.getURLPath());
	} else {
	    defs.put("url", getURLPath());
	}
    }

}
