// CvsDAVFileFrame.java
// $Id: CvsDAVDirectoryFrame.java,v 1.2 2003/03/27 16:38:46 ylafon Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigedit.webdav.frames ;

import java.io.File;
import java.io.IOException;
import java.io.PrintStream;

import org.w3c.tools.resources.Attribute;
import org.w3c.tools.resources.AttributeHolder;
import org.w3c.tools.resources.AttributeRegistry;
import org.w3c.tools.resources.BooleanAttribute;
import org.w3c.tools.resources.DirectoryResource;
import org.w3c.tools.resources.FileResource;
import org.w3c.tools.resources.FramedResource;
import org.w3c.tools.resources.InvalidResourceException;
import org.w3c.tools.resources.MultipleLockException;
import org.w3c.tools.resources.ProtocolException;
import org.w3c.tools.resources.ReplyInterface;
import org.w3c.tools.resources.RequestInterface;
import org.w3c.tools.resources.Resource;
import org.w3c.tools.resources.ResourceException;
import org.w3c.tools.resources.ResourceFrame;
import org.w3c.tools.resources.ResourceReference;
import org.w3c.tools.resources.ServerInterface;

import org.w3c.jigsaw.webdav.DAVFrame;
import org.w3c.jigsaw.webdav.DAVRequest;

import org.w3c.jigsaw.http.HTTPException;
import org.w3c.jigsaw.http.Reply;
import org.w3c.jigsaw.http.Request;

import org.w3c.jigsaw.auth.AuthFilter;

import org.w3c.www.http.HTTP;
import org.w3c.www.http.HttpEntityMessage;
import org.w3c.www.http.HttpMessage;
import org.w3c.www.http.HttpReplyMessage;
import org.w3c.www.http.HttpRequestMessage;

import org.w3c.www.mime.MimeType;

import org.w3c.jigsaw.html.HtmlGenerator;

import org.w3c.cvs.CVS;
import org.w3c.cvs.CvsAddException;
import org.w3c.cvs.CvsDirectory;
import org.w3c.cvs.CvsException;
import org.w3c.cvs.UpToDateCheckFailedException;

import org.w3c.jigedit.cvs.CvsFrame;
import org.w3c.jigedit.cvs.CvsModule;

/**
 * This subclass of HTTPFrame check cvs before performing a PUT request.
 * If a CVS directory exists<BR>
 * <ul>
 * If the resource file exists<BR>
 * <ul> 
 * If resource file not up to date Fail.<BR>
 * Else perform PUT and commit it into cvs.<BR>
 * </ul>
 * Else perform PUT, add and commit it into cvs.<BR>
 * </ul>
 * Else perform PUT.
 * @author Benoit Mahe <bmahe@sophia.inria.fr>
 */

public class CvsDAVDirectoryFrame extends DAVFrame {

    public static final boolean debug = true;

    /**
     * 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;

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

	try {
	    cls = Class.forName("org.w3c.jigedit.webdav.frames"
				+".CvsDAVDirectoryFrame");
	} 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) ;
    }

    protected static Reply error(Request request,
				 int status,
				 String title,
				 String msg) 
    {
	Reply error = request.makeReply(status);
	HtmlGenerator g = CvsFrame.getHtmlGenerator(title);
	g.append("<span class=\"title\">",title,"</span>\n");
	g.append("<p>",msg);
	error.setStream(g);
	return error;
    }

    protected File resDirectory = null;

    protected File getResourceDirectory() {
	if (resDirectory == null) {
	    FramedResource fr = getResource();
	    if (fr instanceof DirectoryResource) {
		resDirectory = ((DirectoryResource) fr).getDirectory();
	    }
	}
	return resDirectory;
    }
    /**
     * tell if we must always do an update.
     */
    public boolean isAutoUpdatable() {
	return getBoolean(ATTR_AUTOUPDATE, false);
    }


    protected synchronized CvsDirectory getCvsManager() 
	throws CvsException
    {
	return CvsModule.getCvsManager(getResourceDirectory(), 
				       getContext(),
				       getServer().getProperties());
    }

    protected boolean checkCvsManager() {
	try {
	    return (getCvsManager() != null);
	} catch (CvsException ex) {
	    return false;
	}
    }

    /**
     * @exception CvsException if the CVS process failed
     */
    protected void add(Request request) 
	throws CvsException
    {
	String u = (String)request.getState(AuthFilter.STATE_AUTHUSER);
	String env[] = {"USER="+u , "LOGNAME="+u };
	String names [] = null;
	MimeType mtype;
        mtype = request.getContentType();
	if (mtype != null && 
	    (mtype.match(MimeType.TEXT) != MimeType.MATCH_SUBTYPE) &&
	    (mtype.match(MimeType.APPLICATION_XHTML_XML) != 
	                    MimeType.MATCH_SPECIFIC_SUBTYPE)) {
	    names = new String[2];
	    names[0] = "-kb";
	    names[1] = getFileResource().getFile().getName();
	} else {
	    names = new String[1];
	    names[0] = getFileResource().getFile().getName();
	}
	CvsDirectory cvsdir = null;
	cvsdir = getCvsManager();
	cvsdir.add(names, env);
    }

    /**
     * @exception CvsException if the CVS process failed
     */
    protected void commit(Request request) 
	throws CvsException
    {
	commit (request, "Changed through Jigsaw.");
    }

    /**
     * @exception CvsException if the CVS process failed
     */
    protected void commit(Request request, String msg) 
	throws CvsException
    {
	String u = (String)request.getState(AuthFilter.STATE_AUTHUSER);
	String env[] = {"USER="+u , "LOGNAME="+u };
	String comment = "("+u+") "+msg;
	CvsDirectory cvsdir = null;
	cvsdir = getCvsManager();
	cvsdir.commit(getFileResource().getFile().getName(), comment, env);
    }

    /**
     * @exception CvsException if the CVS process failed
     */
    protected void update()
	throws CvsException
    {
	CvsDirectory cvsdir = getCvsManager();
	cvsdir.update(getFileResource().getFile().getName());
    }

    /**
     * @exception CvsException if the CVS process failed
     */
    protected int status()
	throws CvsException
    {
	CvsDirectory cvsdir = getCvsManager();
	return cvsdir.status(getFileResource().getFile().getName());
    }

    protected String statusToString(int status) {
	return CvsDirectory.statusToString(status);
    }

    /**
     * Handle the MKCOL request.
     * @param request the WEBDAV request
     * @return a Reply instance
     * @exception ProtocolException If processsing the request failed.
     * @exception ResourceException If the resource got a fatal error.
     */
    public Reply mkcol(DAVRequest request)
	throws ProtocolException, ResourceException
    {
	Reply rep = super.mkcol(request);
	if (rep.getStatus() == HTTP.CREATED) {
	    // we created a new dir, time to add it in cvs
	    String names[] = new String[1];
	    // as the result is HTTP.CREATED, we know for sure that dresource
	    // exists, no need to check.
	    String newcol = (String) request.getState(REMAINING_PATH);
	    names[0] = newcol;
	    try {
		getCvsManager().add(names);
	    } catch (CvsException ex) {
		getServer().errlog(this, ex.getMessage());
	    }
	}
	return rep;
    }
}
