// CvsFileResource.java
// $Id: CvsFileResource.java,v 1.7 1997/07/28 12:48:53 bmahe Exp $
// (c) COPYRIGHT MIT and INRIA, 1996.
// Please first read the full copyright statement in file COPYRIGHT.html

package w3c.jigsaw.contrib;

import java.io.*;

import w3c.jigsaw.resources.*;
import w3c.jigsaw.cvs.*;
import w3c.jigsaw.http.* ;
import w3c.jigsaw.auth.*;
import w3c.www.http.*;
import w3c.cvs.*;

/**
 * This subclass of FileResource 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 CvsFileResource extends FileResource {

  protected File resDirectory = null;
  
  protected synchronized File getResourceDirectory() {
    if (resDirectory == null) {
      HTTPResource p = getParent() ;
      while ((p != null) && ! (p instanceof DirectoryResource) )
	p = p.getParent() ;
      if ( p == null )
	return null;
      resDirectory = ((DirectoryResource) p).getDirectory();
    }
    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] = 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(getFile().getName(), comment, env);
  }

  /**
   * Put a new entity in this resource and update document into 
   * the CvsDirectory (if any).
   * @param request The request to handle.
   */
  public synchronized Reply put(Request request)
    throws HTTPException, ClientException
  {
    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 = 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.put(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.put(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.put(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;
    }
  }

  public CvsFileResource() {}

}
