| /* |
| * Copyright 1999,2006 The Apache Software Foundation. |
| * |
| * Licensed 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 org.apache.log4j.helpers.OptionConverter; |
| |
| import java.io.BufferedWriter; |
| import java.io.File; |
| import java.io.FileNotFoundException; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.io.Writer; |
| |
| |
| // Contibutors: Jens Uwe Pipka <jens.pipka@gmx.de> |
| // Ben Sandee |
| |
| /** |
| * FileAppender appends log events to a file. |
| * |
| * <p>Support for <code>java.io.Writer</code> and console appending |
| * has been deprecated and then removed. See the replacement |
| * solutions: {@link WriterAppender} and {@link ConsoleAppender}. |
| * |
| * @author Ceki Gülcü |
| * */ |
| public class FileAppender extends WriterAppender { |
| |
| /** |
| * The default size of the IO buffer. |
| */ |
| private static final int DEFAULT_BUFFER_SIZE = 8 * 1024; |
| /** |
| * Controls whether to append to or truncate an existing file. |
| * The default value for this variable is |
| * <code>true</code>, meaning that by default a <code>FileAppender</code> will |
| * append to an existing file and not truncate it. |
| * |
| * <p>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; |
| |
| /** |
| The size of the IO buffer. Default is 8K. */ |
| protected int bufferSize = DEFAULT_BUFFER_SIZE; |
| |
| /** |
| The default constructor does not do anything. |
| */ |
| public FileAppender() { |
| } |
| |
| /** |
| Instantiate a <code>FileAppender</code> and open the file |
| designated by <code>filename</code>. The opened filename will |
| become the output destination for this appender. |
| |
| <p>If the <code>append</code> parameter is true, the file will be |
| appended to. Otherwise, the file designated by |
| <code>filename</code> will be truncated before being opened. |
| |
| <p>If the <code>bufferedIO</code> parameter is <code>true</code>, |
| 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); |
| activateOptions(); |
| } |
| |
| /** |
| Instantiate a FileAppender and open the file designated by |
| <code>filename</code>. The opened filename will become the output |
| destination for this appender. |
| |
| <p>If the <code>append</code> parameter is true, the file will be |
| appended to. Otherwise, the file designated by |
| <code>filename</code> 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); |
| activateOptions(); |
| } |
| |
| /** |
| Instantiate a FileAppender and open the file designated by |
| <code>filename</code>. The opened filename will become the output |
| destination for this appender. |
| |
| <p>The file will be appended to. */ |
| public FileAppender(Layout layout, String filename) throws IOException { |
| this(layout, filename, true); |
| activateOptions(); |
| } |
| |
| /** |
| The <b>File</b> property takes a string value which should be the |
| name of the file to append to. |
| |
| <p><font color="#DD0044"><b>Note that the special values |
| "System.out" or "System.err" are no longer honored.</b></font> |
| |
| <p>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 = OptionConverter.stripDuplicateBackslashes(val); |
| } |
| |
| /** |
| Returns the value of the <b>Append</b> option. |
| */ |
| public boolean getAppend() { |
| return fileAppend; |
| } |
| |
| /** Returns the value of the <b>File</b> option. */ |
| public String getFile() { |
| return fileName; |
| } |
| |
| /** |
| If the value of <b>File</b> is not <code>null</code>, then {@link |
| #setFile} is called with the values of <b>File</b> and |
| <b>Append</b> properties. |
| |
| @since 0.8.1 */ |
| public void activateOptions() { |
| if (fileName != null) { |
| try { |
| setFile(fileName, fileAppend, bufferedIO, bufferSize); |
| super.activateOptions(); |
| } catch (java.io.IOException e) { |
| getLogger().error( |
| "setFile(" + fileName + "," + fileAppend + ") call failed.", e); |
| } |
| } else { |
| getLogger().error("File option not set for appender [{}].", name); |
| getLogger().warn("Are you using FileAppender instead of ConsoleAppender?"); |
| } |
| } |
| |
| /** |
| * Closes the previously opened file. |
| * |
| * @deprecated Use the super class' {@link #closeWriter} method instead. |
| */ |
| protected void closeFile() { |
| closeWriter(); |
| } |
| |
| /** |
| Get the value of the <b>BufferedIO</b> option. |
| |
| <p>BufferedIO will significantly 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; |
| } |
| |
| /** |
| The <b>Append</b> option takes a boolean value. It is set to |
| <code>true</code> by default. If true, then <code>File</code> |
| will be opened in append mode by {@link #setFile setFile} (see |
| above). Otherwise, {@link #setFile setFile} will open |
| <code>File</code> in truncate mode. |
| |
| <p>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 <b>BufferedIO</b> option takes a boolean value. It is set to |
| <code>false</code> by default. If true, then <code>File</code> |
| will be opened and the resulting {@link java.io.Writer} wrapped |
| around a {@link BufferedWriter}. |
| |
| BufferedIO will significantly 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; |
| } |
| |
| /** |
| <p>Sets and <i>opens</i> the file where the log output will |
| go. The specified file must be writable. |
| |
| <p>If there was already an opened file, then the previous file |
| is closed first. |
| |
| <p><b>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.</b> |
| |
| @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 setFile( |
| String filename, boolean append, boolean bufferedIO, int bufferSize) |
| throws IOException { |
| getLogger().debug("setFile called: {}, {}", fileName, append?"true":"false"); |
| |
| // It does not make sense to have immediate flush and bufferedIO. |
| if (bufferedIO) { |
| setImmediateFlush(false); |
| } |
| |
| closeWriter(); |
| |
| 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 |
| // |
| File parentDir = new File(new File(filename).getParent()); |
| if(!parentDir.exists() && parentDir.mkdirs()) { |
| ostream = new FileOutputStream(filename, append); |
| } else { |
| throw ex; |
| } |
| } |
| Writer fw = createWriter(ostream); |
| |
| if (bufferedIO) { |
| fw = new BufferedWriter(fw, bufferSize); |
| } |
| setQWForFiles(fw); |
| |
| this.fileAppend = append; |
| this.bufferedIO = bufferedIO; |
| this.fileName = filename; |
| this.bufferSize = bufferSize; |
| writeHeader(); |
| getLogger().debug("setFile ended"); |
| } |
| |
| /** |
| Sets the quiet writer being used. |
| |
| This method is overriden by {@link RollingFileAppender}. |
| */ |
| protected |
| void setQWForFiles(final Writer writer) { |
| this.qw = createQuietWriter(writer); |
| } |
| |
| |
| /** |
| Close any previously opened file and call the parent's |
| <code>reset</code>. |
| @deprecated |
| */ |
| protected |
| void reset() { |
| closeFile(); |
| this.fileName = null; |
| super.reset(); |
| } |
| |
| |
| } |