/*
 * 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.
 */

#ifndef _LOG4CXX_FILE_APPENDER_H
#define _LOG4CXX_FILE_APPENDER_H

#include <log4cxx/logger.h>
#include <log4cxx/logstring.h>
#include <log4cxx/writerappender.h>
#include <log4cxx/file.h>
#include <log4cxx/helpers/pool.h>

#if defined(_MSC_VER)
	#pragma warning ( push )
	#pragma warning ( disable: 4251 )
#endif

namespace log4cxx
{
namespace helpers
{
class Pool;
}

/**
*  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: WriterAppender and ConsoleAppender.
*/
class LOG4CXX_EXPORT FileAppender : public WriterAppender
{
	protected:
		/** Append to or truncate the 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.
		*/
		bool fileAppend;

		/**
		The name of the log file. */
		LogString fileName;

		/**
		Do we do bufferedIO? */
		bool bufferedIO;

		/**
		How big should the IO buffer be? Default is 8K. */
		int bufferSize;

	public:
		DECLARE_LOG4CXX_OBJECT(FileAppender)
		BEGIN_LOG4CXX_CAST_MAP()
		LOG4CXX_CAST_ENTRY(FileAppender)
		LOG4CXX_CAST_ENTRY_CHAIN(WriterAppender)
		END_LOG4CXX_CAST_MAP()

		/**
		The default constructor does not do anything.
		*/
		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.

		*/
		FileAppender(const LayoutPtr& layout, const LogString& filename, bool append,
			bool bufferedIO, int bufferSize);

		/**
		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.
		*/
		FileAppender(const LayoutPtr& layout, const LogString& filename, bool append);

		/**
		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.  */
		FileAppender(const LayoutPtr& layout, const LogString& filename);

		~FileAppender();

		/**
		The <b>File</b> property takes a string value which should be the
		name of the file to append to.

		<p><b>Note that the special values
		"System.out" or "System.err" are no longer honored.</b>

		<p>Note: Actual opening of the file is made when
		#activateOptions is called, not when the options are set.  */
		virtual void setFile(const LogString& file);

		/**
		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 file The path to the log file.
		@param append If true will append to fileName. Otherwise will
		truncate fileName.
		@param bufferedIO Do we do bufferedIO?
		@param bufferSize How big should the IO buffer be?
		@param p memory pool for operation.
		*/
		virtual void setFile(const LogString& file, bool append,
			bool bufferedIO, size_t bufferSize,
			log4cxx::helpers::Pool& p);

		/**
		Returns the value of the <b>Append</b> option.
		*/
		inline bool getAppend() const
		{
			return fileAppend;
		}

		/** Returns the value of the <b>File</b> option. */
		inline LogString getFile() const
		{
			return fileName;
		}

		/**
		<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.*/
		void activateOptions(log4cxx::helpers::Pool& p);
		void setOption(const LogString& option,
			const LogString& value);

		/**
		Get the value of the <b>BufferedIO</b> option.

		<p>BufferedIO will significatnly increase performance on heavily
		loaded systems.

		*/
		inline bool getBufferedIO() const
		{
			return bufferedIO;
		}

		/**
		Get the size of the IO buffer.
		*/
		inline  int getBufferSize() const
		{
			return 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 #setFile (see
		above). Otherwise, setFile will open
		<code>File</code> in truncate mode.

		<p>Note: Actual opening of the file is made when
		#activateOptions is called, not when the options are set.
		*/
		void setAppend(bool fileAppend1);

		/**
		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 in buffered mode.

		BufferedIO will significantly increase performance on heavily
		loaded systems.

		*/
		void setBufferedIO(bool bufferedIO);

		/**
		Set the size of the IO buffer.
		*/
		void setBufferSize(int bufferSize1)
		{
			this->bufferSize = bufferSize1;
		}

		/**
		 *   Replaces double backslashes with single backslashes
		 *   for compatibility with paths from earlier XML configurations files.
		 *   @param name file name
		 *   @return corrected file name
		 */
		static LogString stripDuplicateBackslashes(const LogString& name);

	private:
		FileAppender(const FileAppender&);
		FileAppender& operator=(const FileAppender&);

}; // class FileAppender
LOG4CXX_PTR_DEF(FileAppender);

}  // namespace log4cxx

#if defined(_MSC_VER)
	#pragma warning (pop)
#endif

#endif
