org.apache.log4j.FileAppender Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.log4j;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.Writer;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.QuietWriter;
import org.apache.log4j.spi.ErrorCode;
/**
* FileAppender appends log events to a file.
*
* Support for java.io.Writer
and console appending has been deprecated and then removed. See the
* replacement solutions: {@link WriterAppender} and {@link ConsoleAppender}.
*
*/
public class FileAppender extends WriterAppender {
/**
* Controls file truncatation. The default value for this variable is true
, meaning that by default a
* FileAppender
will append to an existing file and not truncate it.
*
* This option is meaningful only if the FileAppender opens the file.
*
*/
protected boolean fileAppend = true;
/**
* The name of the log file.
*/
protected String fileName = null;
/**
* Do we do bufferedIO?
*/
protected boolean bufferedIO = false;
/**
* Determines the size of IO buffer be. Default is 8K.
*/
protected int bufferSize = 8 * 1024;
/**
* The default constructor does not do anything.
*/
public FileAppender() {
}
/**
* Constructs a FileAppender and open the file designated by filename
. The opened filename will become the
* output destination for this appender.
*
* The file will be appended to.
*
*/
public FileAppender(Layout layout, String filename) throws IOException {
this(layout, filename, true);
}
/**
* Constructs a FileAppender and open the file designated by filename
. The opened filename will become the
* output destination for this appender.
*
* If the append
parameter is true, the file will be appended to. Otherwise, the file designated by
* filename
will be truncated before being opened.
*
*/
public FileAppender(Layout layout, String filename, boolean append) throws IOException {
this.layout = layout;
this.setFile(filename, append, false, bufferSize);
}
/**
* Constructs a FileAppender
and open the file designated by filename
. The opened filename
* will become the output destination for this appender.
*
* If the append
parameter is true, the file will be appended to. Otherwise, the file designated by
* filename
will be truncated before being opened.
*
*
* If the bufferedIO
parameter is true
, then buffered IO will be used to write to the output
* file.
*
*/
public FileAppender(Layout layout, String filename, boolean append, boolean bufferedIO, int bufferSize) throws IOException {
this.layout = layout;
this.setFile(filename, append, bufferedIO, bufferSize);
}
/**
* If the value of File is not null
, then {@link #setFile} is called with the values of File
* and Append properties.
*
* @since 0.8.1
*/
public void activateOptions() {
if (fileName != null) {
try {
setFile(fileName, fileAppend, bufferedIO, bufferSize);
} catch (java.io.IOException e) {
errorHandler.error("setFile(" + fileName + "," + fileAppend + ") call failed.", e, ErrorCode.FILE_OPEN_FAILURE);
}
} else {
// LogLog.error("File option not set for appender ["+name+"].");
LogLog.warn("File option not set for appender [" + name + "].");
LogLog.warn("Are you using FileAppender instead of ConsoleAppender?");
}
}
/**
* Closes the previously opened file.
*/
protected void closeFile() {
if (this.qw != null) {
try {
this.qw.close();
} catch (java.io.IOException e) {
if (e instanceof InterruptedIOException) {
Thread.currentThread().interrupt();
}
// Exceptionally, it does not make sense to delegate to an
// ErrorHandler. Since a closed appender is basically dead.
LogLog.error("Could not close " + qw, e);
}
}
}
/**
* Returns the value of the Append option.
*/
public boolean getAppend() {
return fileAppend;
}
/**
* Get the value of the BufferedIO option.
*
*
* BufferedIO will significatnly increase performance on heavily loaded systems.
*
*/
public boolean getBufferedIO() {
return this.bufferedIO;
}
/**
* Get the size of the IO buffer.
*/
public int getBufferSize() {
return this.bufferSize;
}
/** Returns the value of the File option. */
public String getFile() {
return fileName;
}
/**
* Close any previously opened file and call the parent's reset
.
*/
protected void reset() {
closeFile();
this.fileName = null;
super.reset();
}
/**
* The Append option takes a boolean value. It is set to true
by default. If true, then
* File
will be opened in append mode by {@link #setFile setFile} (see above). Otherwise, {@link #setFile
* setFile} will open File
in truncate mode.
*
*
* Note: Actual opening of the file is made when {@link #activateOptions} is called, not when the options are set.
*
*/
public void setAppend(boolean flag) {
fileAppend = flag;
}
/**
* The BufferedIO option takes a boolean value. It is set to false
by default. If true, then
* File
will be opened and the resulting {@link java.io.Writer} wrapped around a {@link BufferedWriter}.
*
* BufferedIO will significatnly increase performance on heavily loaded systems.
*
*/
public void setBufferedIO(boolean bufferedIO) {
this.bufferedIO = bufferedIO;
if (bufferedIO) {
immediateFlush = false;
}
}
/**
* Set the size of the IO buffer.
*/
public void setBufferSize(int bufferSize) {
this.bufferSize = bufferSize;
}
/**
* The File property takes a string value which should be the name of the file to append to.
*
* Note that the special values "System.out" or "System.err" are no longer honored.
*
*
* Note: Actual opening of the file is made when {@link #activateOptions} is called, not when the options are set.
*
*/
public void setFile(String file) {
// Trim spaces from both ends. The users probably does not want
// trailing spaces in file names.
String val = file.trim();
fileName = val;
}
/**
* 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 activateOptions.
*
*
* @param fileName The path to the log file.
* @param append If true will append to fileName. Otherwise will truncate fileName.
*/
public synchronized void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize) throws IOException {
LogLog.debug("setFile called: " + fileName + ", " + append);
// It does not make sense to have immediate flush and bufferedIO.
if (bufferedIO) {
setImmediateFlush(false);
}
reset();
FileOutputStream ostream = null;
try {
//
// attempt to create file
//
ostream = new FileOutputStream(fileName, append);
} catch (FileNotFoundException ex) {
//
// if parent directory does not exist then
// attempt to create it and try to create file
// see bug 9150
//
String parentName = new File(fileName).getParent();
if (parentName != null) {
File parentDir = new File(parentName);
if (!parentDir.exists() && parentDir.mkdirs()) {
ostream = new FileOutputStream(fileName, append);
} else {
throw ex;
}
} else {
throw ex;
}
}
Writer fw = createWriter(ostream);
if (bufferedIO) {
fw = new BufferedWriter(fw, bufferSize);
}
this.setQWForFiles(fw);
this.fileName = fileName;
this.fileAppend = append;
this.bufferedIO = bufferedIO;
this.bufferSize = bufferSize;
writeHeader();
LogLog.debug("setFile ended");
}
/**
* Sets the quiet writer being used.
*
* This method is overriden by {@link RollingFileAppender}.
*/
protected void setQWForFiles(Writer writer) {
this.qw = new QuietWriter(writer, errorHandler);
}
}