All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ch.qos.logback.core.FileAppender Maven / Gradle / Ivy

There is a newer version: 1.2
Show newest version
/**
 * Logback: the reliable, generic, fast and flexible logging framework.
 * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
 *
 * This program and the accompanying materials are dual-licensed under
 * either the terms of the Eclipse Public License v1.0 as published by
 * the Eclipse Foundation
 *
 *   or (per the licensee's choosing)
 *
 * under the terms of the GNU Lesser General Public License version 2.1
 * as published by the Free Software Foundation.
 */
package ch.qos.logback.core;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.Writer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;

import ch.qos.logback.core.util.FileUtil;

/**
 * FileAppender appends log events to a file.
 * 
 * For more information about this appender, please refer to the online manual
 * at http://logback.qos.ch/manual/appenders.html#FileAppender
 * 
 * @author Ceki Gülcü
 */
public class FileAppender extends WriterAppender {

  /**
   * Append to or truncate the file? The default value for this variable is
   * true, meaning that by default a FileAppender
   * will append to an existing file and not truncate it.
   */
  protected boolean append = true;

  /**
   * The name of the active log file.
   */
  protected String fileName = null;

  /**
   * Do we do bufferedIO?
   */
  protected boolean bufferedIO = false;

  /**
   * The size of the IO buffer. Default is 8K.
   */
  protected int bufferSize = 8 * 1024;

  private boolean prudent = false;

  private FileChannel fileChannel = null;

  /**
   * As in most cases, the default constructor does nothing.
   */
  public FileAppender() {
  }

  /**
   * The File property takes a string value which should be the name of
   * the file to append to.
   */
  public void setFile(String file) {
    if (file == null) {
      fileName = file;
    } else {
      // Trim spaces from both ends. The users probably does not want
      // trailing spaces in file names.
      String val = file.trim();
      fileName = val;
    }
  }

  /**
   * @deprecated Use isAppend instead
   */
  public boolean getAppend() {
    return append;
  }

  /**
   * Returns the value of the Append property.
   */
  public boolean isAppend() {
    return append;
  }

  /**
   * This method is used by derived classes to obtain the raw file property.
   * Regular users should not be calling this method.
   * 
   * @return the value of the file property
   */
  final public String rawFileProperty() {
    return fileName;
  }

  /**
   * Returns the value of the File property.
   * 
   * 

This method may be overridden by derived classes. * */ public String getFile() { return fileName; } /** * If the value of File is not null, then * {@link #openFile} is called with the values of File and Append * properties. */ public void start() { int errors = 0; if (getFile() != null) { addInfo("File property is set to [" + fileName + "]"); if (prudent) { if (isAppend() == false) { setAppend(true); addWarn("Setting \"Append\" property to true on account of \"Prudent\" mode"); } if (getImmediateFlush() == false) { setImmediateFlush(true); addWarn("Setting \"ImmediateFlush\" to true on account of \"Prudent\" mode"); } if (bufferedIO == true) { setBufferedIO(false); addWarn("Setting \"BufferedIO\" property to false on account of \"Prudent\" mode"); } } // In case both bufferedIO and immediateFlush are set, the former // takes priority because 'immediateFlush' is set to true by default. // If the user explicitly set bufferedIO, then we should follow her // directives. if (bufferedIO) { setImmediateFlush(false); addInfo("Setting \"ImmediateFlush\" property to false on account of \"bufferedIO\" property"); } try { openFile(getFile()); } catch (java.io.IOException e) { errors++; addError("openFile(" + fileName + "," + append + ") call failed.", e); } } else { errors++; addError("\"File\" property not set for appender named [" + name + "]."); } if (errors == 0) { super.start(); } } /** *

Sets and opens the file where the log output will go. The * specified file must be writable. * *

If there was already an opened file, then the previous file is closed * first. * *

Do not use this method directly. To configure a FileAppender or one * of its subclasses, set its properties one by one and then call start(). * * @param filename * The path to the log file. * @param append * If true will append to fileName. Otherwise will truncate * fileName. * @param bufferedIO * @param bufferSize * * @throws IOException * */ public synchronized void openFile(String file_name) throws IOException { File file = new File(file_name); if (FileUtil.mustCreateParentDirectories(file)) { boolean result = FileUtil.createMissingParentDirectories(file); if (!result) { addError("Failed to create parent directories for [" + file.getAbsolutePath() + "]"); } } FileOutputStream fileOutputStream = new FileOutputStream(file_name, append); if (prudent) { fileChannel = fileOutputStream.getChannel(); } Writer w = createWriter(fileOutputStream); if (bufferedIO) { w = new BufferedWriter(w, bufferSize); } setWriter(w); } public boolean isBufferedIO() { return bufferedIO; } public void setBufferedIO(boolean bufferedIO) { this.bufferedIO = bufferedIO; } public int getBufferSize() { return bufferSize; } public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize; } /** * @see #setPrudent(boolean) * * @return true if in prudent mode */ public boolean isPrudent() { return prudent; } /** * When prudent is set to true, file appenders from multiple JVMs can safely * write to the same file. * * @param prudent */ public void setPrudent(boolean prudent) { this.prudent = prudent; } public void setAppend(boolean append) { this.append = append; } final private void safeWrite(String s) throws IOException { FileLock fileLock = null; try { fileLock = fileChannel.lock(); long position = fileChannel.position(); long size = fileChannel.size(); if (size != position) { fileChannel.position(size); } super.writerWrite(s, true); } finally { if (fileLock != null) { fileLock.release(); } } } @Override protected void writerWrite(String s, boolean flush) throws IOException { if (prudent && fileChannel != null) { safeWrite(s); } else { super.writerWrite(s, flush); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy