// CvsFileFrame.java
// $Id: CvsFileFrame.java,v 1.3 1998/02/12 12:51:48 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 indexer to produce something. This breaks 
	// below code, and makes the size checking mandatory
	if (resfile.exists() && (resfile.length() > 0)) {
	  try {
	    if (CvsDir.status(resfile.getName()) ==  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;
    }
  }

}
