// AutoLookupDirectory.java
// $Id: AutoLookupDirectory.java,v 1.4 1998/04/23 12:32:28 bmahe Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigsaw.cvs ;

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

import org.w3c.cvs.*;
import org.w3c.tools.resources.*;
import org.w3c.jigsaw.resources.*;
import org.w3c.www.http.*;
import org.w3c.jigsaw.http.*;

/**
 * A special version of DirectoryResource that can fetch a file
 * from CVS directly if it is not already here.
 * It can alos do an automatic update, depending on a flag
 */


public class AutoLookupDirectory 
       extends org.w3c.jigsaw.resources.DirectoryResource
{

    private CvsDirectory cvs = null ;

    /**
     * Attribute index, tell if we must update the resource everytime it is
     * acceded (not recommended as it generates many cvs commands)
     */

    private static int ATTR_AUTOUPDATE = -1;

    /**
     * Attribute index, tell if we must add into cvs new puted directories.
     */
    private static int ATTR_EXTENSIBLE = -1;
  
    static {
	Attribute   a = null ;
	Class     cls = null;
    
	try {
	    cls     = Class.forName("org.w3c.jigsaw.cvs.AutoLookupDirectory") ;
	} catch (Exception ex) {
	    ex.printStackTrace() ;
	    System.exit(1) ;
	}
	// The browsable flag:
	a = new BooleanAttribute("autoupdate",
				 Boolean.FALSE,
				 Attribute.EDITABLE) ;
	ATTR_AUTOUPDATE = AttributeRegistry.registerAttribute(cls, a) ;
        // The browsable flag:
	a = new BooleanAttribute("cvs-extensible",
				 Boolean.FALSE,
				 Attribute.EDITABLE) ;
	ATTR_EXTENSIBLE = AttributeRegistry.registerAttribute(cls, a) ;
    }


    /**
     * Get the appropriate CVS manager for the directory we handle.
     * @return A CvsDirectory instance.
     * @exception CvsException If we couldn't get the manager.
     */

    protected synchronized CvsDirectory getCvsManager() 
	throws CvsException
    {
	if ( cvs == null ) {
	    cvs = CvsDirectory.getManager(getDirectory(),
					  getServer().getProperties());
	}
	return cvs;
    }

	    
    /**
     * tell if we must always do an update.
     */

    public boolean isAutoUpdatable() {
	return getBoolean(ATTR_AUTOUPDATE, false);
    }

    /**
     * tell if we must add in cvs the new puted documents.
     */
    public boolean isCvsExtensible() {
	return getBoolean(ATTR_EXTENSIBLE, false);
    }

    /**
     * Create a DirectoryResource and the physical directory too.
     * Add the new directory in the CVS repository.
     * @param name the name of the resource.
     * @return A ResourceReference instance.
     */
    public ResourceReference createDirectoryResource(String name) {
	ResourceReference newdir = super.createDirectoryResource(name);
	if ((newdir != null) && isCvsExtensible()) {
	    String names[] = new String[1];
	    names[0] = name;
	    try {
		getCvsManager().add(names);
	    } catch (CvsException ex) {
		ex.printStackTrace();
	    }
	}
	return newdir;
    }

    /**
     * Lookup the resource having the given name in this directory.
     * if the resource is not present, it will try to fetch it from
     * the Cvs repository.
     * @param name The name of the resource.
     * @return A ResourceReference instance, or <strong>null</strong>.
     */

    public ResourceReference lookup(String name) {
	ResourceReference rr = super.lookup(name);
	if (rr != null) {
	    try {
		Resource resource = rr.lock();
		// If it's a FileResource, and cvs update enabled, do it:
		if ( isAutoUpdatable() && (resource instanceof FileResource)) {
		    FileResource fr = (FileResource) resource;
		    String filename = fr.getFilename();
		    if (filename == null)
			filename = name;
		    try {
			if (getCvsManager().status(filename)!=CVS.FILE_OK)
			    getCvsManager().update(filename);
		    } catch (CvsException ex) {
			String msg = "cvs update \""+filename+"\" failed.";
			getServer().errlog(this, msg);
		    }
		}
	    } catch (InvalidResourceException ex) {
		return rr;
	    } finally {
		rr.unlock();
	    }
	    return rr;
	} else {
	    // This may be an unchecked out directory:
	    try {
		if ( getCvsManager().getDirectoryStatus(name) == CVS.DIR_NCO )
		    getCvsManager().updateDirectory(name);
	    } catch (CvsException ex) {
		String msg = "cvs update -d \""+name+"\" failed.";
		getServer().errlog(this, msg);
		return null;
	    }
	    // Checking out the directory succeeded, retry lookup:
	    return super.lookup(name);
	}
    }

}
