/* FileHandler.java -- a class for publishing log messages to log files
   Copyright (C) 2002, 2003, 2004, 2005  Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
General Public License for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */


package java.util.logging;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.ListIterator;

/**
 * A <code>FileHandler</code> publishes log records to a set of log
 * files.  A maximum file size can be specified; as soon as a log file
 * reaches the size limit, it is closed and the next file in the set
 * is taken.
 *
 * <p><strong>Configuration:</strong> Values of the subsequent
 * <code>LogManager</code> properties are taken into consideration
 * when a <code>FileHandler</code> is initialized.  If a property is
 * not defined, or if it has an invalid value, a default is taken
 * without an exception being thrown.
 *
 * <ul>
 *
 * <li><code>java.util.FileHandler.level</code> - specifies
 *     the initial severity level threshold. Default value:
 *     <code>Level.ALL</code>.</li>
 *
 * <li><code>java.util.FileHandler.filter</code> - specifies
 *     the name of a Filter class. Default value: No Filter.</li>
 *
 * <li><code>java.util.FileHandler.formatter</code> - specifies
 *     the name of a Formatter class. Default value:
 *     <code>java.util.logging.XMLFormatter</code>.</li>
 *
 * <li><code>java.util.FileHandler.encoding</code> - specifies
 *     the name of the character encoding. Default value:
 *     the default platform encoding.</li>
 *
 * <li><code>java.util.FileHandler.limit</code> - specifies the number
 *     of bytes a log file is approximately allowed to reach before it
 *     is closed and the handler switches to the next file in the
 *     rotating set.  A value of zero means that files can grow
 *     without limit.  Default value: 0 (unlimited growth).</li>
 *
 * <li><code>java.util.FileHandler.count</code> - specifies the number
 *     of log files through which this handler cycles.  Default value:
 *     1.</li>
 *
 * <li><code>java.util.FileHandler.pattern</code> - specifies a
 *     pattern for the location and name of the produced log files.
 *     See the section on <a href="#filePatterns">file name
 *     patterns</a> for details.  Default value:
 *     <code>"%h/java%u.log"</code>.</li>
 *
 * <li><code>java.util.FileHandler.append</code> - specifies
 *     whether the handler will append log records to existing
 *     files, or whether the handler will clear log files
 *     upon switching to them. Default value: <code>false</code>,
 *     indicating that files will be cleared.</li>
 *
 * </ul>
 *
 * <p><a name="filePatterns"><strong>File Name Patterns:</strong></a>
 * The name and location and log files are specified with pattern
 * strings. The handler will replace the following character sequences
 * when opening log files:
 *
 * <p><ul>
 * <li><code>/</code> - replaced by the platform-specific path name
 *     separator.  This value is taken from the system property
 *     <code>file.separator</code>.</li>
 *
 * <li><code>%t</code> - replaced by the platform-specific location of
 *     the directory intended for temporary files.  This value is
 *     taken from the system property <code>java.io.tmpdir</code>.</li>
 *
 * <li><code>%h</code> - replaced by the location of the home
 *     directory of the current user.  This value is taken from the
 *     system property <code>file.separator</code>.</li>
 *
 * <li><code>%g</code> - replaced by a generation number for
 *     distinguisthing the individual items in the rotating set 
 *     of log files.  The generation number cycles through the
 *     sequence 0, 1, ..., <code>count</code> - 1.</li>
 *
 * <li><code>%u</code> - replaced by a unique number for
 *     distinguisthing the output files of several concurrently
 *     running processes.  The <code>FileHandler</code> starts
 *     with 0 when it tries to open a log file.  If the file
 *     cannot be opened because it is currently in use,
 *     the unique number is incremented by one and opening
 *     is tried again.  These steps are repeated until the
 *     opening operation succeeds.
 *
 *     <p>FIXME: Is the following correct? Please review.  The unique
 *     number is determined for each log file individually when it is
 *     opened upon switching to the next file.  Therefore, it is not
 *     correct to assume that all log files in a rotating set bear the
 *     same unique number.
 *
 *     <p>FIXME: The Javadoc for the Sun reference implementation
 *     says: "Note that the use of unique ids to avoid conflicts is
 *     only guaranteed to work reliably when using a local disk file
 *     system." Why? This needs to be mentioned as well, in case
 *     the reviewers decide the statement is true.  Otherwise,
 *     file a bug report with Sun.</li>
 *
 * <li><code>%%</code> - replaced by a single percent sign.</li>
 * </ul>
 *
 * <p>If the pattern string does not contain <code>%g</code> and
 * <code>count</code> is greater than one, the handler will append
 * the string <code>.%g</code> to the specified pattern.
 *
 * <p>If the handler attempts to open a log file, this log file
 * is being used at the time of the attempt, and the pattern string
 * does not contain <code>%u</code>, the handler will append
 * the string <code>.%u</code> to the specified pattern. This
 * step is performed after any generation number has been
 * appended.
 *
 * <p><em>Examples for the GNU platform:</em> 
 *
 * <p><ul>
 *
 * <li><code>%h/java%u.log</code> will lead to a single log file
 *     <code>/home/janet/java0.log</code>, assuming <code>count</code>
 *     equals 1, the user's home directory is
 *     <code>/home/janet</code>, and the attempt to open the file
 *     succeeds.</li>
 *
 * <li><code>%h/java%u.log</code> will lead to three log files
 *     <code>/home/janet/java0.log.0</code>,
 *     <code>/home/janet/java0.log.1</code>, and
 *     <code>/home/janet/java0.log.2</code>,
 *     assuming <code>count</code> equals 3, the user's home
 *     directory is <code>/home/janet</code>, and all attempts
 *     to open files succeed.</li>
 *
 * <li><code>%h/java%u.log</code> will lead to three log files
 *     <code>/home/janet/java0.log.0</code>,
 *     <code>/home/janet/java1.log.1</code>, and
 *     <code>/home/janet/java0.log.2</code>,
 *     assuming <code>count</code> equals 3, the user's home
 *     directory is <code>/home/janet</code>, and the attempt
 *     to open <code>/home/janet/java0.log.1</code> fails.</li>
 *
 * </ul>
 *
 * @author Sascha Brawer (brawer@acm.org)
 */
public class FileHandler
  extends StreamHandler
{
  /**
   * The number of bytes a log file is approximately allowed to reach
   * before it is closed and the handler switches to the next file in
   * the rotating set.  A value of zero means that files can grow
   * without limit.
   */
  private final int limit;


 /**
  * The number of log files through which this handler cycles.
  */
  private final int count;


  /**
   * The pattern for the location and name of the produced log files.
   * See the section on <a href="#filePatterns">file name patterns</a>
   * for details.
   */
  private final String pattern;


  /**
   * Indicates whether the handler will append log records to existing
   * files (<code>true</code>), or whether the handler will clear log files
   * upon switching to them (<code>false</code>).
   */
  private final boolean append;


  /**
   * The number of bytes that have currently been written to the stream.
   * Package private for use in inner classes.
   */
  long written;


  /**
   * A linked list of files we are, or have written to. The entries
   * are file path strings, kept in the order 
   */
  private LinkedList logFiles;


  /**
   * Constructs a <code>FileHandler</code>, taking all property values
   * from the current {@link LogManager LogManager} configuration.
   *
   * @throws java.io.IOException FIXME: The Sun Javadoc says: "if
   *         there are IO problems opening the files."  This conflicts
   *         with the general principle that configuration errors do
   *         not prohibit construction. Needs review.
   *
   * @throws SecurityException if a security manager exists and
   *         the caller is not granted the permission to control
   *         the logging infrastructure.
   */
  public FileHandler()
    throws IOException, SecurityException
  {
    this(/* pattern: use configiguration */ null,

	 LogManager.getIntProperty("java.util.logging.FileHandler.limit",
				   /* default */ 0),

	 LogManager.getIntProperty("java.util.logging.FileHandler.count",
				   /* default */ 1),

	 LogManager.getBooleanProperty("java.util.logging.FileHandler.append",
				       /* default */ false));
  }


  /* FIXME: Javadoc missing. */
  public FileHandler(String pattern)
    throws IOException, SecurityException
  {
    this(pattern,
	 /* limit */ 0,
	 /* count */ 1,
	 /* append */ false);
  }


  /* FIXME: Javadoc missing. */
  public FileHandler(String pattern, boolean append)
    throws IOException, SecurityException
  {
    this(pattern,
	 /* limit */ 0,
	 /* count */ 1,
	 append);
  }


  /* FIXME: Javadoc missing. */
  public FileHandler(String pattern, int limit, int count)
    throws IOException, SecurityException
  {
    this(pattern, limit, count, 
	 LogManager.getBooleanProperty(
	   "java.util.logging.FileHandler.append",
	   /* default */ false));
  }


  /**
   * Constructs a <code>FileHandler</code> given the pattern for the
   * location and name of the produced log files, the size limit, the
   * number of log files thorough which the handler will rotate, and
   * the <code>append</code> property.  All other property values are
   * taken from the current {@link LogManager LogManager}
   * configuration.
   *
   * @param pattern The pattern for the location and name of the
   *        produced log files.  See the section on <a
   *        href="#filePatterns">file name patterns</a> for details.
   *        If <code>pattern</code> is <code>null</code>, the value is
   *        taken from the {@link LogManager LogManager} configuration
   *        property
   *        <code>java.util.logging.FileHandler.pattern</code>.
   *        However, this is a pecularity of the GNU implementation,
   *        and Sun's API specification does not mention what behavior
   *        is to be expected for <code>null</code>. Therefore,
   *        applications should not rely on this feature.
   *
   * @param limit specifies the number of bytes a log file is
   *        approximately allowed to reach before it is closed and the
   *        handler switches to the next file in the rotating set.  A
   *        value of zero means that files can grow without limit.
   *
   * @param count specifies the number of log files through which this
   *        handler cycles.
   *
   * @param append specifies whether the handler will append log
   *        records to existing files (<code>true</code>), or whether the
   *        handler will clear log files upon switching to them
   *        (<code>false</code>).
   *
   * @throws java.io.IOException FIXME: The Sun Javadoc says: "if
   *         there are IO problems opening the files."  This conflicts
   *         with the general principle that configuration errors do
   *         not prohibit construction. Needs review.
   *
   * @throws SecurityException if a security manager exists and
   *         the caller is not granted the permission to control
   *         the logging infrastructure.
   *         <p>FIXME: This seems in contrast to all other handler
   *         constructors -- verify this by running tests against
   *         the Sun reference implementation.
   */
  public FileHandler(String pattern,
		     int limit,
		     int count,
		     boolean append)
    throws IOException, SecurityException
  {
    super(/* output stream, created below */ null,
	  "java.util.logging.FileHandler",
	  /* default level */ Level.ALL,
	  /* formatter */ null,
	  /* default formatter */ XMLFormatter.class);

    if ((limit <0) || (count < 1))
      throw new IllegalArgumentException();

    this.pattern = pattern;
    this.limit = limit;
    this.count = count;
    this.append = append;
    this.written = 0;
    this.logFiles = new LinkedList ();

    setOutputStream (createFileStream (pattern, limit, count, append,
                                       /* generation */ 0));
  }


  /* FIXME: Javadoc missing. */
  private OutputStream createFileStream(String pattern,
                                        int limit,
                                        int count,
                                        boolean append,
                                        int generation)
  {
    String  path;
    int     unique = 0;

    /* Throws a SecurityException if the caller does not have
     * LoggingPermission("control").
     */
    LogManager.getLogManager().checkAccess();

    /* Default value from the java.util.logging.FileHandler.pattern
     * LogManager configuration property.
     */
    if (pattern == null)
      pattern = LogManager.getLogManager().getProperty(
                              "java.util.logging.FileHandler.pattern");
    if (pattern == null)
      pattern = "%h/java%u.log";

    if (count > 1 && !has (pattern, 'g'))
      pattern = pattern + ".%g";

    do
    {
      path = replaceFileNameEscapes(pattern, generation, unique, count);

      try
      {
	File file = new File(path);
        if (!file.exists () || append)
          {
            FileOutputStream fout = new FileOutputStream (file, append);
            // FIXME we need file locks for this to work properly, but they
            // are not implemented yet in Classpath! Madness!
//             FileChannel channel = fout.getChannel ();
//             FileLock lock = channel.tryLock ();
//             if (lock != null) // We've locked the file.
//               {
                if (logFiles.isEmpty ())
                  logFiles.addFirst (path);
                return new ostr (fout);
//               }
          }
      }
      catch (Exception ex)
      {
        reportError (null, ex, ErrorManager.OPEN_FAILURE);
      }

      unique = unique + 1;
      if (!has (pattern, 'u'))
        pattern = pattern + ".%u";
    }
    while (true);
  }


  /**
   * Replaces the substrings <code>"/"</code> by the value of the
   * system property <code>"file.separator"</code>, <code>"%t"</code>
   * by the value of the system property
   * <code>"java.io.tmpdir"</code>, <code>"%h"</code> by the value of
   * the system property <code>"user.home"</code>, <code>"%g"</code>
   * by the value of <code>generation</code>, <code>"%u"</code> by the
   * value of <code>uniqueNumber</code>, and <code>"%%"</code> by a
   * single percent character.  If <code>pattern</code> does
   * <em>not</em> contain the sequence <code>"%g"</code>,
   * the value of <code>generation</code> will be appended to
   * the result.
   *
   * @throws NullPointerException if one of the system properties
   *         <code>"file.separator"</code>,
   *         <code>"java.io.tmpdir"</code>, or
   *         <code>"user.home"</code> has no value and the
   *         corresponding escape sequence appears in
   *         <code>pattern</code>.
   */
  private static String replaceFileNameEscapes(String pattern,
					       int generation,
					       int uniqueNumber,
					       int count)
  {
    StringBuffer buf = new StringBuffer(pattern);
    String       replaceWith;
    boolean      foundGeneration = false;

    int pos = 0;
    do
    {
      // Uncomment the next line for finding bugs.
      // System.out.println(buf.substring(0,pos) + '|' + buf.substring(pos));
      
      if (buf.charAt(pos) == '/')
      {
	/* The same value is also provided by java.io.File.separator. */
	replaceWith = System.getProperty("file.separator");
	buf.replace(pos, pos + 1, replaceWith);
	pos = pos + replaceWith.length() - 1;
	continue;
      }

      if (buf.charAt(pos) == '%')
      {
        switch (buf.charAt(pos + 1))
	{
	case 't':
	  replaceWith = System.getProperty("java.io.tmpdir");
	  break;

	case 'h':
	  replaceWith = System.getProperty("user.home");
	  break;

	case 'g':
	  replaceWith = Integer.toString(generation);
	  foundGeneration = true;
	  break;

	case 'u':
	  replaceWith = Integer.toString(uniqueNumber);
	  break;

	case '%':
	  replaceWith = "%";
	  break;

	default:
	  replaceWith = "??";
	  break; // FIXME: Throw exception?
	}

	buf.replace(pos, pos + 2, replaceWith);
	pos = pos + replaceWith.length() - 1;
	continue;
      }
    }
    while (++pos < buf.length() - 1);

    if (!foundGeneration && (count > 1))
    {
      buf.append('.');
      buf.append(generation);
    }

    return buf.toString();
  }


  /* FIXME: Javadoc missing. */
  public void publish(LogRecord record)
  {
    if (limit > 0 && written >= limit)
      rotate ();
    super.publish(record);
    flush ();
  }

  /**
   * Rotates the current log files, possibly removing one if we
   * exceed the file count.
   */
  private synchronized void rotate ()
  {
    if (logFiles.size () > 0)
      {
        File f1 = null;
        ListIterator lit = null;

        // If we reach the file count, ditch the oldest file.
        if (logFiles.size () == count)
          {
            f1 = new File ((String) logFiles.getLast ());
            f1.delete ();
            lit = logFiles.listIterator (logFiles.size () - 1);
          }
        // Otherwise, move the oldest to a new location.
        else
          {
            String path = replaceFileNameEscapes (pattern, logFiles.size (),
                                                  /* unique */ 0, count);
            f1 = new File (path);
            logFiles.addLast (path);
            lit = logFiles.listIterator (logFiles.size () - 1);
          }

        // Now rotate the files.
        while (lit.hasPrevious ())
          {
            String s = (String) lit.previous ();
            File f2 = new File (s);
            f2.renameTo (f1);
            f1 = f2;
          }
      }

    setOutputStream (createFileStream (pattern, limit, count, append,
                                       /* generation */ 0));

    // Reset written count.
    written = 0;
  }

  /**
   * Tell if <code>pattern</code> contains the pattern sequence
   * with character <code>escape</code>. That is, if <code>escape</code>
   * is 'g', this method returns true if the given pattern contains
   * "%g", and not just the substring "%g" (for example, in the case of
   * "%%g").
   *
   * @param pattern The pattern to test.
   * @param escape The escape character to search for.
   * @return True iff the pattern contains the escape sequence with the
   *  given character.
   */
  private static boolean has (final String pattern, final char escape)
  {
    final int len = pattern.length ();
    boolean sawPercent = false;
    for (int i = 0; i < len; i++)
      {
        char c = pattern.charAt (i);
        if (sawPercent)
          {
            if (c == escape)
              return true;
            if (c == '%') // Double percent
              {
                sawPercent = false;
                continue;
              }
          }
        sawPercent = (c == '%');
      }
    return false;
  }

  /**
   * An output stream that tracks the number of bytes written to it.
   */
  private final class ostr extends FilterOutputStream
  {
    private ostr (OutputStream out)
    {
      super (out);
    }

    public void write (final int b) throws IOException
    {
      out.write (b);
      FileHandler.this.written++; // FIXME: synchronize?
    }

    public void write (final byte[] b) throws IOException
    {
      write (b, 0, b.length);
    }

    public void write (final byte[] b, final int offset, final int length)
      throws IOException
    {
      out.write (b, offset, length);
      FileHandler.this.written += length; // FIXME: synchronize?
    }
  }
}
