// ExtendedCommonLogger.java
// $Id: ExtendedCommonLogger.java,v 1.3 1999/02/18 13:27:56 ylafon Exp $
// (c) COPYRIGHT MIT and INRIA, 1999.
// Please first read the full copyright statement in file COPYRIGHT.html

package org.w3c.jigsaw.http ;

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

import org.w3c.jigsaw.daemon.*;
import org.w3c.jigsaw.auth.AuthFilter;
import org.w3c.util.*;

/**
 * The ExtendedCommonLogger class implements the abstract Logger class.
 * It just rotates the log every month and use the extended log format
 * @see org.w3c.jigsaw.http.CommonLogger
 */


public class ExtendedCommonLogger extends CommonLogger {
    private int month = -1;
    private int year  = -1;
    private int  tz   = -1;

    private static final String monthnames[] = {
	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
	"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
    };
	
    /**
     * Name of the property indicating the log file.
     * This property indicates the name of the log file to use.
     * <p>This property defaults to the <code>log</code> file in the server
     * log directory.
     */
    public static final 
    String LOGNAME_P = "org.w3c.jigsaw.logger.logname" ;
    /**
     * Name of the property indicating the error log file.
     * This property indicates the name of the error log file to use.
     * <p>This property defaults to the <code>errlog</code> file in the
     * server log directory.
     */
    public static final 
    String ERRLOGNAME_P = "org.w3c.jigsaw.logger.errlogname" ;
    /**
     * Name of the property indicating the server trace file.
     * This property indicates the name of the trace file to use.
     * <p>This property defaults to the <code>trace</code> file in the 
     * server log directory.
     */
    public static final 
    String TRACELOGNAME_P = "org.w3c.jigsaw.logger.tracelogname";
    /**
     * Name of the property indicating the buffer size for the logger.
     * This buffer size applies only the the log file, not to the error
     * log file, or the trace log file. It can be set to zero if you want
     * no buffering.
     * <p>This property default to <strong>4096</strong>.
     */
    public static final 
    String BUFSIZE_P = "org.w3c.jigsaw.logger.bufferSize";

    private   byte                 msgbuf[] = null ;

    protected void openLogFile() {
	// do nothing
    }

    protected void openLogFile(int year, int month) {
	this.year = year;
	this.month = month;
	
	String ext = null;
	if (month < 9)
	    ext = "_"+year+"_0"+(month+1);
	else
	    ext = "_"+year+"_"+(month+1);

	String logname = getFilename(LOGNAME_P, "log") + ext;
	try {
	    RandomAccessFile old = log ;
	    log = new RandomAccessFile (logname, "rw") ;
	    log.seek (log.length()) ;
	    if ( old != null )
		old.close () ;
	} catch (IOException e) {
	    throw new HTTPRuntimeException (this.getClass().getName()
					    , "openLogFile"
					    , "unable to open "+logname);
	}
    }

    /**
     * Log the given HTTP transaction.
     * This is shamelessly slow.
     */

    public void log (Request request, Reply reply, int nbytes, long duration) {
	Client client = request.getClient() ;
	String entry  = null ;
	long   date   = reply.getDate();
	// Compute the time zone offset, first call only.
	if ( tz == -1 ) {
	    tz = new Date().getTimezoneOffset();
	}
	Date   now    = (date < 0) ? new Date() : new Date(date+(tz*60*1000));

	if ((now.getYear()+1900) != year || now.getMonth() != month) {
	    if (log!= null) {
		sync();
		try {
		    log.close();
		} catch (IOException ex) {};
		log = null;
	    }
	    openLogFile(now.getYear()+1900, now.getMonth());
	}
	String user = (String) request.getState(AuthFilter.STATE_AUTHUSER);

	entry = client.getInetAddress().getHostAddress()
	    + " " + "-"			  	   // user name
	    + " " + ((user == null ) ? "-" : user) // auth user name
	    + ((now.getDate() < 10) ? " [0" : " [")
	    + (now.getDate() 		   	   // current date
	       + "/" + monthnames[now.getMonth()]
	       + "/" + (now.getYear() + 1900)
	       + ((now.getHours() < 10)
		  ? (":0" + now.getHours())
		  : (":" + now.getHours()))
	       + ((now.getMinutes() < 10)
		  ? (":0" + now.getMinutes())
		  : (":" + now.getMinutes()))
	       + ((now.getSeconds() < 10)
		  ? (":0" + now.getSeconds())
		  : (":" + now.getSeconds()))
	       + ((date<0) ?
		  ((now.getTimezoneOffset() < 0)
		   ? " " + (now.getTimezoneOffset() / 60)
		   : " +" + (now.getTimezoneOffset() / 60))
		  : " +0")
	       + "]")
	    + " \"" + request.getMethod()	// request line
	    + " " + request.getURL()
	    + " " + request.getVersion()
	    + "\" " + reply.getStatus()		// reply status
	    + " " + nbytes			// # of emited bytes
	    + " \"" + 
	    ((request.getReferer() == null) ? "-" : request.getReferer())
	    + "\"" // the referer (ext log)
	    + " \"" + 
	    ((request.getUserAgent() == null) ? "-" : request.getUserAgent())
	    + "\"" // User agent
	    + "\n" ;
	logmsg (entry) ;
    }
    
    /**
     * Construct a new Logger instance.
     */
     
    ExtendedCommonLogger () {
	this.msgbuf = new byte[128] ;
    }   
    
}
