2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.apache.log4j;
20 import java.io.BufferedWriter;
22 import java.io.FileNotFoundException;
23 import java.io.FileOutputStream;
24 import java.io.IOException;
25 import java.io.InterruptedIOException;
26 import java.io.Writer;
28 import org.apache.log4j.helpers.LogLog;
29 import org.apache.log4j.helpers.QuietWriter;
30 import org.apache.log4j.spi.ErrorCode;
32 // Contibutors: Jens Uwe Pipka <jens.pipka@gmx.de>
36 * FileAppender appends log events to a file.
38 * <p>Support for <code>java.io.Writer</code> and console appending
39 * has been deprecated and then removed. See the replacement
40 * solutions: {@link WriterAppender} and {@link ConsoleAppender}.
42 * @author Ceki Gülcü
44 public class FileAppender extends WriterAppender {
46 /** Controls file truncatation. The default value for this variable
47 * is <code>true</code>, meaning that by default a
48 * <code>FileAppender</code> will append to an existing file and not
51 * <p>This option is meaningful only if the FileAppender opens the
54 protected boolean fileAppend = true;
57 The name of the log file. */
58 protected String fileName = null;
61 Do we do bufferedIO? */
62 protected boolean bufferedIO = false;
65 * Determines the size of IO buffer be. Default is 8K.
67 protected int bufferSize = 8*1024;
71 The default constructor does not do anything.
78 Instantiate a <code>FileAppender</code> and open the file
79 designated by <code>filename</code>. The opened filename will
80 become the output destination for this appender.
82 <p>If the <code>append</code> parameter is true, the file will be
83 appended to. Otherwise, the file designated by
84 <code>filename</code> will be truncated before being opened.
86 <p>If the <code>bufferedIO</code> parameter is <code>true</code>,
87 then buffered IO will be used to write to the output file.
91 FileAppender(Layout layout, String filename, boolean append, boolean bufferedIO,
92 int bufferSize) throws IOException {
94 this.setFile(filename, append, bufferedIO, bufferSize);
98 Instantiate a FileAppender and open the file designated by
99 <code>filename</code>. The opened filename will become the output
100 destination for this appender.
102 <p>If the <code>append</code> parameter is true, the file will be
103 appended to. Otherwise, the file designated by
104 <code>filename</code> will be truncated before being opened.
107 FileAppender(Layout layout, String filename, boolean append)
109 this.layout = layout;
110 this.setFile(filename, append, false, bufferSize);
114 Instantiate a FileAppender and open the file designated by
115 <code>filename</code>. The opened filename will become the output
116 destination for this appender.
118 <p>The file will be appended to. */
120 FileAppender(Layout layout, String filename) throws IOException {
121 this(layout, filename, true);
125 The <b>File</b> property takes a string value which should be the
126 name of the file to append to.
128 <p><font color="#DD0044"><b>Note that the special values
129 "System.out" or "System.err" are no longer honored.</b></font>
131 <p>Note: Actual opening of the file is made when {@link
132 #activateOptions} is called, not when the options are set. */
133 public void setFile(String file) {
134 // Trim spaces from both ends. The users probably does not want
135 // trailing spaces in file names.
136 String val = file.trim();
141 Returns the value of the <b>Append</b> option.
144 boolean getAppend() {
149 /** Returns the value of the <b>File</b> option. */
156 If the value of <b>File</b> is not <code>null</code>, then {@link
157 #setFile} is called with the values of <b>File</b> and
158 <b>Append</b> properties.
162 void activateOptions() {
163 if(fileName != null) {
165 setFile(fileName, fileAppend, bufferedIO, bufferSize);
167 catch(java.io.IOException e) {
168 errorHandler.error("setFile("+fileName+","+fileAppend+") call failed.",
169 e, ErrorCode.FILE_OPEN_FAILURE);
172 //LogLog.error("File option not set for appender ["+name+"].");
173 LogLog.warn("File option not set for appender ["+name+"].");
174 LogLog.warn("Are you using FileAppender instead of ConsoleAppender?");
179 Closes the previously opened file.
183 if(this.qw != null) {
187 catch(java.io.IOException e) {
188 if (e instanceof InterruptedIOException) {
189 Thread.currentThread().interrupt();
191 // Exceptionally, it does not make sense to delegate to an
192 // ErrorHandler. Since a closed appender is basically dead.
193 LogLog.error("Could not close " + qw, e);
199 Get the value of the <b>BufferedIO</b> option.
201 <p>BufferedIO will significatnly increase performance on heavily
206 boolean getBufferedIO() {
207 return this.bufferedIO;
212 Get the size of the IO buffer.
215 int getBufferSize() {
216 return this.bufferSize;
222 The <b>Append</b> option takes a boolean value. It is set to
223 <code>true</code> by default. If true, then <code>File</code>
224 will be opened in append mode by {@link #setFile setFile} (see
225 above). Otherwise, {@link #setFile setFile} will open
226 <code>File</code> in truncate mode.
228 <p>Note: Actual opening of the file is made when {@link
229 #activateOptions} is called, not when the options are set.
232 void setAppend(boolean flag) {
237 The <b>BufferedIO</b> option takes a boolean value. It is set to
238 <code>false</code> by default. If true, then <code>File</code>
239 will be opened and the resulting {@link java.io.Writer} wrapped
240 around a {@link BufferedWriter}.
242 BufferedIO will significatnly increase performance on heavily
247 void setBufferedIO(boolean bufferedIO) {
248 this.bufferedIO = bufferedIO;
250 immediateFlush = false;
256 Set the size of the IO buffer.
259 void setBufferSize(int bufferSize) {
260 this.bufferSize = bufferSize;
264 <p>Sets and <i>opens</i> the file where the log output will
265 go. The specified file must be writable.
267 <p>If there was already an opened file, then the previous file
270 <p><b>Do not use this method directly. To configure a FileAppender
271 or one of its subclasses, set its properties one by one and then
272 call activateOptions.</b>
274 @param fileName The path to the log file.
275 @param append If true will append to fileName. Otherwise will
276 truncate fileName. */
279 void setFile(String fileName, boolean append, boolean bufferedIO, int bufferSize)
281 LogLog.debug("setFile called: "+fileName+", "+append);
283 // It does not make sense to have immediate flush and bufferedIO.
285 setImmediateFlush(false);
289 FileOutputStream ostream = null;
292 // attempt to create file
294 ostream = new FileOutputStream(fileName, append);
295 } catch(FileNotFoundException ex) {
297 // if parent directory does not exist then
298 // attempt to create it and try to create file
301 String parentName = new File(fileName).getParent();
302 if (parentName != null) {
303 File parentDir = new File(parentName);
304 if(!parentDir.exists() && parentDir.mkdirs()) {
305 ostream = new FileOutputStream(fileName, append);
313 Writer fw = createWriter(ostream);
315 fw = new BufferedWriter(fw, bufferSize);
317 this.setQWForFiles(fw);
318 this.fileName = fileName;
319 this.fileAppend = append;
320 this.bufferedIO = bufferedIO;
321 this.bufferSize = bufferSize;
323 LogLog.debug("setFile ended");
328 Sets the quiet writer being used.
330 This method is overriden by {@link RollingFileAppender}.
333 void setQWForFiles(Writer writer) {
334 this.qw = new QuietWriter(writer, errorHandler);
339 Close any previously opened file and call the parent's
340 <code>reset</code>. */
344 this.fileName = null;