// VirtualHostResource.java
// $Id: VirtualHostResource.java,v 1.2 1997/06/09 12:31:53 bmahe Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.tools.resources.http;

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

import w3c.tools.resources.*;
import w3c.tools.resources.Resource;
import w3c.tools.resources.LookupState;
import w3c.tools.resources.impl.*;
import w3c.tools.resources.indexer.*;

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

public class VirtualHostResource extends ResourceContainerImpl {
  
  protected String followupName = null;

  public String getFollowupName () {
    return (String)holder.protectedGetValue("followupName");
  }

  public void setFollowupName (String followupName) {
    holder.protectedSetValue("followupName",followupName);
  }

  public String igetFollowupName () {
    return followupName;
  }

  public void isetFollowupName (String followupName) {
    this.followupName = followupName;
  }  

  protected HTTPResource followup = 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 ResourceReference 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).
   */

  public synchronized void registerChild(String id
					 , Resource resource
					 , ResourceContext context)
    throws ResourceInitException, ChildNotSupportedException
  {
    // FIXME, I don't think it's that, may be I have to append
    // name of the resource and id in the context name property.
    context.addProperty("name",id);
    super.registerChild(resource,context);
  }

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

  public synchronized ResourceReference loadChild(String host) {
    ResourceReference rr  = super.loadChild(host);
    HTTPResource resource = null;
    if (rr != null) {
      try {
	resource = (HTTPResource)rr.lock();
	resource.setUrlPath("http://"+host);
      } finally {
	rr.unlock();
	return rr;
      }
    } else {
      return null;
    }
  }

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

  public synchronized HTTPResource lookupFollowup() {
    if ( followup == null ) {
      String name  = getFollowupName();
      // FIXME server.loadRoot !!!
      //      if ( name != null ) 
      //	followup = getServer().loadRoot(name);
      if ( followup == null ) {
	getServer().errlog(getName()
			   + "[" + 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 ResourceReference resolve(LookupState state) 
  {
    // If this is an internal lookup, it's pretty easy:
    if ( state.isInternal() ) {
      return super.resolve(state);
    }
    // Try to lookup on the host header:
    ResourceReference rr = null;
    HTTPResource vroot = null;
    Request r = state.getRequest();
    String host = null;
    if ( r != null )
      host = r.getHost();
    if ( host != null )
      rr = loadChild(host.toLowerCase());
    try {
      if (rr != null)
	vroot = (HTTPResource)rr.lock();
      if (vroot == null)
	vroot  = lookupFollowup();
      return (vroot == null) ? super.resolve(state) : vroot.resolve(state);
    } finally {
      if (rr != null) rr.unlock();
    }
  }

  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 init(ResourceContext context) 
    throws ResourceInitException
  {
    super.init(context);
    ResourceReference rr = getParent();
    if (rr != null) {
      try {
	HTTPResource parent = (HTTPResource)rr.lock();
	context.addProperty("urlPath",parent.getUrlPath());
      } finally {
	rr.unlock();
      }
    } else {
      context.addProperty("urlPath",getUrlPath());
    }
  }

}
