/*
 * 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_HELPERS_ONLY_ONCE_ERROR_HANDLER_H
#define _LOG4CXX_HELPERS_ONLY_ONCE_ERROR_HANDLER_H

#include <log4cxx/spi/errorhandler.h>
#include <log4cxx/helpers/objectimpl.h>

#ifdef _MSC_VER
#pragma warning ( push )
#pragma warning (disable : 4251) // ::std::exception needs to have dll-interface
#endif

namespace log4cxx
{
namespace helpers
{
/**
The <code>OnlyOnceErrorHandler</code> implements log4cxx's default
error handling policy which consists of emitting a message for the
first error in an appender and ignoring all following errors.

<p>The error message is printed on <code>System.err</code>.

<p>This policy aims at protecting an otherwise working application
from being flooded with error messages when logging fails
*/
class LOG4CXX_EXPORT OnlyOnceErrorHandler :
	public virtual spi::ErrorHandler,
	public virtual ObjectImpl
{
	private:
		LogString WARN_PREFIX;
		LogString ERROR_PREFIX;
		mutable bool firstTime;

	public:
		DECLARE_LOG4CXX_OBJECT(OnlyOnceErrorHandler)
		BEGIN_LOG4CXX_CAST_MAP()
		LOG4CXX_CAST_ENTRY(spi::OptionHandler)
		LOG4CXX_CAST_ENTRY(spi::ErrorHandler)
		END_LOG4CXX_CAST_MAP()

		OnlyOnceErrorHandler();
		void addRef() const;
		void releaseRef() const;

		/**
		 Does not do anything.
		 */
		void setLogger(const LoggerPtr& logger);


		/**
		No options to activate.
		*/
		void activateOptions(log4cxx::helpers::Pool& p);
		void setOption(const LogString& option, const LogString& value);


		/**
		Prints the message and the stack trace of the exception on
		<code>System.err</code>.  */
		void error(const LogString& message, const std::exception& e,
			int errorCode) const;
		/**
		Prints the message and the stack trace of the exception on
		<code>System.err</code>.
		*/
		void error(const LogString& message, const std::exception& e,
			int errorCode, const spi::LoggingEventPtr& event) const;

		/**
		Print a the error message passed as parameter on
		<code>System.err</code>.
		*/
		void error(const LogString& message) const;

		/**
		Does not do anything.
		*/
		void setAppender(const AppenderPtr& appender);

		/**
		Does not do anything.
		*/
		void setBackupAppender(const AppenderPtr& appender);
};
}  // namespace helpers
} // namespace log4cxx

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

#endif //_LOG4CXX_HELPERS_ONLY_ONCE_ERROR_HANDLER_H

