// MirrorDirectory.java
// $Id: MirrorDirectory.java,v 1.5 1997/08/04 07:02:12 abaird Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.proxy ;

import java.net.*;
import java.io.*;

import w3c.tools.store.*;
import w3c.www.http.*;
import w3c.jigsaw.http.*;
import w3c.jigsaw.resources.*;

/**
 * Mirror a whole site, right there.
 */

public class MirrorDirectory extends ForwardDirectory {
    /**
     * Attribute index - The site we are mirroring.
     */
    protected static int ATTR_MIRRORS = -1;

    static {
	Class     c = null;
	Attribute a = null;
	try {
	    c = Class.forName("w3c.jigsaw.proxy.MirrorDirectory");
	} catch (Exception ex) {
	    ex.printStackTrace();
	    System.exit(1);
	}
	// Register the mirrored site attribute:
	a = new StringAttribute("mirrors"
				, null
				, Attribute.EDITABLE);
	ATTR_MIRRORS = AttributeRegistry.registerAttribute(c, a);
    }

    protected URL mirrors = null;

    /**
     * Get the mirrors site attribute value.
     * @return The String encoded URL of the site we are mirroring here.
     */

    public String getMirrors() {
	return getString(ATTR_MIRRORS, null);
    }

    /**
     * Catch assignment to the mirror attribute, to update our cached URL.
     * @param idx The slot to set.
     * @param value It's new value.
     */

    public void setValue(int idx, Object value) {
	super.setValue(idx, value);
	if ( idx == ATTR_MIRRORS ) {
	    try {
		mirrors = new URL(getMirrors());
	    } catch (Exception ex) {
		mirrors = null;
	    }
	}
    }

    protected Reply dupReply(Request request
			     , w3c.www.protocol.http.Reply rep) 
	throws HTTPException, IOException
    {
	Reply reply = super.dupReply(request, rep);
	// Tweak redirections ! Wow this is getting real nifty :-)
	switch(reply.getStatus()) {
	  case HTTP.MOVED_PERMANENTLY:
	  case HTTP.MOVED_TEMPORARILY:
	  case HTTP.SEE_OTHER:
	      // Have fun !
	      String location = rep.getLocation();
	      if ((mirrors != null) && (location != null)) {
		  try {
		      URL uloc = new URL(mirrors, location);
		      URL loc  = getURL(request);
		      URL fake = new URL("http"
					 , loc.getHost()
					 , loc.getPort()
					 , uloc.getFile());
		      reply.setLocation(fake);
		  } catch (Exception ex) {
		  }
		  return reply;
	      }
	}
	return reply;
    }
    protected w3c.www.protocol.http.Request dupRequest(Request request) 
	throws HTTPException, IOException
    {
	w3c.www.protocol.http.Request req = super.dupRequest(request);
	// Tweak the URL :-)
	req.setURL(new URL(mirrors, request.getURL().getFile()));
	return req;
    }
		
    /**
     * Lookup for a mirrored  resource.
     * @param request The request whose URI is to be looked up.
     * @exception HTTPException If something fails.
     */

    public boolean lookup(LookupState ls, LookupResult lr) 
	throws HTTPException
    {
	// Get the full URL from the request:
	Request request = ls.getRequest();
	URL     url     = request.getURL() ;
        boolean superResult = super.lookup(ls, lr);

	if ( ls.isInternal() )
	    return superResult;
	// Is this really belonging to the site we are mirroring ?
	if ( mirrors != null ) {
	    request.setProxy(true);
	    lr.setTarget(this);
	    return true;
	} 
	// Emit a not found:
	Reply error = request.makeReply(HTTP.NOT_FOUND);
	error.setContent("Target resource not found.");
	lr.setTarget(null);
	lr.setReply(error);
	return true;
    }

    public void initialize(Object values[]) {
	super.initialize(values);
	String strmirrors = getMirrors();
	try {
	    mirrors = new URL(strmirrors);
	} catch (Exception ex) {
	    mirrors = null;
	}
    }

}
