// RelocateResource.java
// $Id: RelocateResource.java,v 1.6 1997/01/27 13:23:10 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 java.net.*;

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

/**
 * This resource will always emit a relocation to some given URL.
 */


public class RelocateResource extends FilteredResource {
    /**
     * Name of the state to hold the PATH_INFO in the request.
     */
    public final static 
    String PATH_INFO = "w3c.jigsaw.resources.RelocateResource.PathInfo";

    /**
     * Attribute index - The relocation location.
     */
    protected static int ATTR_LOCATION = -1 ;
    /**
     * Attribute index - Should we also handle extra path infos ?
     */
    protected static int ATTR_HANDLE_PATHINFO = -1;

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

	try {
	    c = Class.forName("w3c.jigsaw.resources.RelocateResource");
	} catch (Exception ex) {
	    ex.printStackTrace() ;
	    System.exit(1) ;
	}
	// The location attribute
	a = new StringAttribute("location"
				, null
				, Attribute.EDITABLE|Attribute.MANDATORY) ;
	ATTR_LOCATION = AttributeRegistry.registerAttribute(c, a) ;
	// The handle path info attribute
	a = new BooleanAttribute("handle-pathinfo"
				 , Boolean.TRUE
				 , Attribute.EDITABLE);
	ATTR_HANDLE_PATHINFO = AttributeRegistry.registerAttribute(c, a);
    }

    /**
     * Get the location for the relocation
     */

    public String getLocation() {
	return (String) getValue(ATTR_LOCATION, null) ;
    }

    public boolean checkHandlePathInfo() {
	return getBoolean(ATTR_HANDLE_PATHINFO, true);
    }

    public boolean lookup(LookupState ls, LookupResult lr) 
	throws HTTPException
    {
	// Perform our super-class lookup strategy:
	if ( super.lookup(ls, lr) ) {
	    return true;
	} else if ( ! checkHandlePathInfo() ) {
	    return false;
	}
	// Compute PATH INFO, store it as a piece of state in the request:
	StringBuffer pathinfo = new StringBuffer();
	while ( ls.hasMoreComponents() ) {
	    pathinfo.append('/');
	    pathinfo.append(ls.getNextComponent());
	}
	if (ls.hasRequest() ) {
	    Request request = ls.getRequest();
	    request.setState(PATH_INFO, pathinfo.toString());
	}
	lr.setTarget(this);
	return true;
    }
	
    /**
     * Emit a redirect.
     * All GET requests are redirected toward the target location.
     * @param client The client issuing the request.
     * @param request The request to handle.
     * @exception HTTPException If the request couldn't be handled.
     */

    public Reply get (Request request)
	throws HTTPException
    {
	String location = getLocation() ;
	if ( location == null ) {
	    Reply error = request.makeReply(HTTP.INTERNAL_SERVER_ERROR) ;
	    error.setContent("The target RelocateResource doesn't define the"
			     + " relocation location. The server is "
			     + " misconfigured.") ;
	    throw new HTTPException(error) ;
	} else {
	    Reply  reply    = request.makeReply(HTTP.MOVED_TEMPORARILY) ;
	    URL    loc      = null;
	    try {
		loc = new URL(getURL(request), location);
		if (checkHandlePathInfo()) {
		    String pathinfo = (String) request.getState(PATH_INFO);
		    // Given the way pathinfo is computed, it starts with a /
		    loc = new URL(loc, pathinfo.substring(1));
		}
	    } catch (Exception ex) {
		ex.printStackTrace();
	    }
	    reply.setLocation(loc);
	    return reply ;
	}
    }
	
}
