// CvsFileFrame.java
// $Id: CvsFileFrame.java,v 1.5 1998/07/06 15:54:26 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 org.w3c.tools.resources.*;
import org.w3c.jigsaw.frames.*;
import org.w3c.jigsaw.http.* ;
import org.w3c.jigsaw.auth.*;
import org.w3c.www.http.*;
import org.w3c.cvs.*;


/**
 * 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 CvsFileFrame extends HTTPFrame {

    protected File resDirectory = null;

    protected synchronized File getResourceDirectory() {
	if (resDirectory == null) {
	    ResourceReference rr = getFileResource().getParent();
	    ResourceReference rrtemp = null;
	    Resource p = null;
	    while ( true ) {
		try {
		    if (rr == null)
			return null;
		    p = rr.lock();
		    if (p instanceof DirectoryResource) {
			resDirectory = ((DirectoryResource)p).getDirectory();
			break;
		    }
		    rrtemp = p.getParent();
		} catch (InvalidResourceException ex) {
		    return null;
		} finally {
		    if (rr != null)
			rr.unlock();
		}
		rr = rrtemp;
	    }
	}
	return resDirectory;
    }
  
    protected void add(Request request) 
	throws CvsException
    {
	String u = (String)request.getState(AuthFilter.STATE_AUTHUSER);
	String env[] = {"USER="+u , "LOGNAME="+u };
	String names [] = new String[1];
	names[0] = getFileResource().getFile().getName();
	CvsDirectory cvsdir = null;
	cvsdir = CvsDirectory.getManager(getResourceDirectory(),
					 getServer().getProperties());
	cvsdir.add(names, env);
    }

    protected void commit(Request request) 
	throws CvsException
    {
	String u = (String)request.getState(AuthFilter.STATE_AUTHUSER);
	String env[] = {"USER="+u , "LOGNAME="+u };
	String comment = "("+u+") Changed through Jigsaw.";
	CvsDirectory cvsdir = null;
	cvsdir = CvsDirectory.getManager(getResourceDirectory(),
					 getServer().getProperties());
	cvsdir.commit(getFileResource().getFile().getName(), comment, env);
    }

    protected Reply putFileResource(Request request)
	throws ProtocolException, NotAProtocolException
    {
	if (getResourceDirectory() != null) {
	    CvsDirectory CvsDir = null;

	    try {
		CvsDir = CvsDirectory.getManager(getResourceDirectory(),
						 getServer().getProperties());
	    } catch (CvsException ex) {
		getServer().errlog(this, ex.getMessage());
		ex.printStackTrace();
	    }

	    if (CvsDir != null) {
		File resfile = getFileResource().getFile();
		// ### FIXME There is a bug in PutableDirectory 
		// (it creates an empty file to allow for the 
		// to produce something. This breaks 
		// below code, and makes the size checking mandatory
		//if (resfile.exists() && (resfile.length() > 0)) {
		int cvs_status = -1;
		try {
		    cvs_status = CvsDir.status(resfile.getName());
		} catch (CvsException ex) {
		    ex.printStackTrace();
		    Reply r = request.makeReply(HTTP.SERVICE_UNAVAILABLE);
		    r.setContent("CvsException : "+ex.getMessage());
		    getServer().errlog(getIdentifier()+" : "
				       +ex.getMessage());
		    return r;
		}
		if (resfile.exists() && (cvs_status != CVS.FILE_Q)) {
		    try {
			if (cvs_status ==  CVS.FILE_OK) {
				// Write the file to web space
			    Reply r = super.putFileResource(request);
				// Do a CVS commit with user name
			    commit(request);
			    return r;
			} else {
				// fail
			    Reply r = request.makeReply(
				                     HTTP.SERVICE_UNAVAILABLE);
			    r.setContent("File is not up to date, "+
					 "please update the file manually.");
			    return r;
			}
		    } catch (CvsException ex) { 
			// fail too 
			ex.printStackTrace();
			Reply r = request.makeReply(HTTP.SERVICE_UNAVAILABLE);
			r.setContent("CvsException : "+ex.getMessage());
			getServer().errlog(getIdentifier()+" : "
					   +ex.getMessage());
			return r;
		    }
		} else {
		    // Write the file to web space
		    Reply r = super.putFileResource(request);
		    try {
			//  Do a CVS add with user name
			add(request);
			//  Do a CVS commit with user name
			commit(request);
		    } catch (CvsException ex) {
			ex.printStackTrace();
			String msg = "Problem during cvs process : "
			    +ex.getMessage();
			getServer().errlog(getIdentifier()+" : "+msg);
			r = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
			r.setContent(msg);
		    }
		    return r;
		}
	    } 
	    else 
		return super.putFileResource(request);
	} else {
	    String msg = "Server misconfigured : "+
		"unable to find resource directory";
	    getServer().errlog(getIdentifier()+" : "+msg);
	    Reply r = request.makeReply(HTTP.INTERNAL_SERVER_ERROR);
	    r.setContent(msg);
	    return r;
	}
    }
}
