/*
 * 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_PROPERTY_CONFIGURATOR_H
#define _LOG4CXX_PROPERTY_CONFIGURATOR_H

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


#include <log4cxx/helpers/objectptr.h>
#include <log4cxx/helpers/objectimpl.h>
#include <log4cxx/logstring.h>
#include <log4cxx/spi/configurator.h>
#include <map>

#include <log4cxx/file.h>

namespace log4cxx
{
   class Logger;
   typedef helpers::ObjectPtrT<Logger> LoggerPtr;

   class Appender;
   typedef helpers::ObjectPtrT<Appender> AppenderPtr;

   namespace helpers
   {
      class Properties;
   }


    namespace spi {
        class LoggerFactory;
    }

	class PropertyWatchdog;
/**
Allows the configuration of log4cxx from an external file.  See
<b>{@link #doConfigure(const File&, log4cxx::spi::LoggerRepositoryPtr&)}</b>
for the expected format.

<p>It is sometimes useful to see how log4cxx is reading configuration
files. You can enable log4cxx internal logging by defining the
<b>log4j.debug</b> variable.

<P>At class initialization time class,
the file <b>log4j.properties</b> will be searched in the current directory.
If the file can be found, then it will
be fed to the
{@link PropertyConfigurator#configure(const File& configFilename)}
method.

<p>The <code>PropertyConfigurator</code> does not handle the
advanced configuration features supported by the {@link
xml::DOMConfigurator DOMConfigurator} such as
support for {@link spi::Filter Filters}, custom
{@link spi::ErrorHandler ErrorHandlers}, nested
appenders such as the {@link AsyncAppender
AsyncAppender}, etc.

<p>All option <em>values</em> admit variable substitution. The
syntax of variable substitution is similar to that of Unix
shells. The string between an opening <b>&quot;${&quot;</b> and
closing <b>&quot;}&quot;</b> is interpreted as a key. The value of
the substituted variable can be defined as a system property or in
the configuration file itself. The value of the key is first
searched in the system properties, and if not found there, it is
then searched in the configuration file being parsed.  The
corresponding value replaces the ${variableName} sequence. For
example, if <code>java.home</code> system property is set to
<code>/home/xyz</code>, then every occurrence of the sequence
<code>${java.home}</code> will be interpreted as
<code>/home/xyz</code>.
*/
   class LOG4CXX_EXPORT PropertyConfigurator :
      virtual public spi::Configurator,
      virtual public helpers::ObjectImpl
   {
   protected:

      /**
      Used internally to keep track of configured appenders.
      */
      std::map<LogString, AppenderPtr>* registry;

      /**
      Used to create new instances of logger
      */
        helpers::ObjectPtrT<spi::LoggerFactory> loggerFactory;

   public:
      DECLARE_LOG4CXX_OBJECT(PropertyConfigurator)
      BEGIN_LOG4CXX_CAST_MAP()
         LOG4CXX_CAST_ENTRY(spi::Configurator)
      END_LOG4CXX_CAST_MAP()

      PropertyConfigurator();
      virtual ~PropertyConfigurator();
      void addRef() const;
      void releaseRef() const;

/**
Read configuration from a file. <b>The existing configuration is
not cleared nor reset.</b> If you require a different behavior,
then call {@link LogManager#resetConfiguration
resetConfiguration} method before calling
<code>doConfigure</code>.

<p>The configuration file consists of statements in the format
<code>key=value</code>. The syntax of different configuration
elements are discussed below.

<h3>Repository-wide threshold</h3>

<p>The repository-wide threshold filters logging requests by level
regardless of logger. The syntax is:

<pre>
log4j.threshold=[level]
</pre>

<p>The level value can consist of the string values OFF, FATAL,
ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</em> value. A
custom level value can be specified in the form
level#classname. By default the repository-wide threshold is set
to the lowest possible value, namely the level <code>ALL</code>.
</p>


<h3>Appender configuration</h3>

<p>Appender configuration syntax is:
<pre>
# For appender named <i>appenderName</i>, set its class.
# Note: The appender name can contain dots.
log4j.appender.appenderName=fully.qualified.name.of.appender.class

# Set appender specific options.
log4j.appender.appenderName.option1=value1
...
log4j.appender.appenderName.optionN=valueN
</pre>

For each named appender you can configure its {@link Layout Layout}. The
syntax for configuring an appender's layout is:
<pre>
log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
log4j.appender.appenderName.layout.option1=value1
....
log4j.appender.appenderName.layout.optionN=valueN
</pre>

<h3>Configuring loggers</h3>

<p>The syntax for configuring the root logger is:
<pre>
log4j.rootLogger=[level], appenderName, appenderName, ...
</pre>

<p>This syntax means that an optional <em>level</em> can be
supplied followed by appender names separated by commas.

<p>The level value can consist of the string values OFF, FATAL,
ERROR, WARN, INFO, DEBUG, ALL or a <em>custom level</em> value. A
custom level value can be specified in the form
<code>level#classname</code>.

<p>If a level value is specified, then the root level is set
to the corresponding level.  If no level value is specified,
then the root level remains untouched.

<p>The root logger can be assigned multiple appenders.

<p>Each <i>appenderName</i> (separated by commas) will be added to
the root logger. The named appender is defined using the
appender syntax defined above.

<p>For non-root categories the syntax is almost the same:
<pre>
log4j.logger.logger_name=[level|INHERITED|NULL], appenderName, appenderName,
...
</pre>

<p>The meaning of the optional level value is discussed above
in relation to the root logger. In addition however, the value
INHERITED can be specified meaning that the named logger should
inherit its level from the logger hierarchy.

<p>If no level value is supplied, then the level of the
named logger remains untouched.

<p>By default categories inherit their level from the
hierarchy. However, if you set the level of a logger and later
decide that that logger should inherit its level, then you should
specify INHERITED as the value for the level value. NULL is a
synonym for INHERITED.

<p>Similar to the root logger syntax, each <i>appenderName</i>
(separated by commas) will be attached to the named logger.

<p>See the <a href="Introduction.html#additivity">appender
additivity rule</a> in the user manual for the meaning of the
<code>additivity</code> flag.

<h3>Logger Factories</h3>

The usage of custom logger factories is discouraged and no longer
documented.

<h3>Example</h3>

<p>An example configuration is given below. Other configuration
file examples are given in the <code>examples</code> folder.

<pre>

# Set options for appender named "A1".
# Appender "A1" will be a SyslogAppender
log4j.appender.A1=SyslogAppender

# The syslog daemon resides on www.abc.net
log4j.appender.A1.SyslogHost=www.abc.net

# A1's layout is a PatternLayout, using the conversion pattern
# <b>%r %-5p %c{2} %M.%L %x - %m\n</b>. Thus, the log output will
# include # the relative time since the start of the application in
# milliseconds, followed by the level of the log request,
# followed by the two rightmost components of the logger name,
# followed by the callers method name, followed by the line number,
# the nested disgnostic context and finally the message itself.
# Refer to the documentation of PatternLayout for further information
# on the syntax of the ConversionPattern key.
log4j.appender.A1.layout=PatternLayout
log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} %M.%L %x - %m\n

# Set options for appender named "A2"
# A2 should be a RollingFileAppender, with maximum file size of 10 MB
# using at most one backup file. A2's layout is TTCC, using the
# ISO8061 date format with context printing enabled.
log4j.appender.A2=RollingFileAppender
log4j.appender.A2.MaxFileSize=10MB
log4j.appender.A2.MaxBackupIndex=1
log4j.appender.A2.layout=TTCCLayout
log4j.appender.A2.layout.ContextPrinting=enabled
log4j.appender.A2.layout.DateFormat=ISO8601

# Root logger set to DEBUG using the A2 appender defined above.
log4j.rootLogger=DEBUG, A2

# Logger definitions:
# The SECURITY logger inherits is level from root. However, it's output
# will go to A1 appender defined above. It's additivity is non-cumulative.
log4j.logger.SECURITY=INHERIT, A1
log4j.additivity.SECURITY=false

# Only warnings or above will be logged for the logger "SECURITY.access".
# Output will go to A1.
log4j.logger.SECURITY.access=WARN


# The logger "class.of.the.day" inherits its level from the
# logger hierarchy.  Output will go to the appender's of the root
# logger, A2 in this case.
log4j.logger.class.of.the.day=INHERIT
</pre>

<p>Refer to the <b>setOption</b> method in each Appender and
Layout for class specific options.

<p>Use the <code>#</code> or <code>!</code> characters at the
beginning of a line for comments.

<p>
@param configFileName The name of the configuration file where the
configuration information is stored.
@param hierarchy The hierarchy to operation upon.
*/
      void doConfigure(const File& configFileName,
         spi::LoggerRepositoryPtr& hierarchy);

      /**
      Read configuration options from file <code>configFilename</code>.
      */
      static void configure(const File& configFilename);

      /**
      Like {@link #configureAndWatch(const File& configFilename, long delay)}
      except that the
      default delay as defined by helpers::FileWatchdog#DEFAULT_DELAY
      is used.
      @param configFilename A file in key=value format.
      */
      static void configureAndWatch(const File& configFilename);

      /**
      Read the configuration file <code>configFilename</code> if it
      exists. Moreover, a thread will be created that will periodically
      check if <code>configFilename</code> has been created or
      modified. The period is determined by the <code>delay</code>
      argument. If a change or file creation is detected, then
      <code>configFilename</code> is read to configure log4j.

      @param configFilename A file in key=value format.
      @param delay The delay in milliseconds to wait between each check.
      */
      static void configureAndWatch(const File& configFilename,
         long delay);

      /**
      Read configuration options from <code>properties</code>.
      See #doConfigure(const File&, log4cxx::spi::LoggerRepositoryPtr&)
      for the expected format.
      */
      static void configure(helpers::Properties& properties);

      /**
      Read configuration options from <code>properties</code>.
      See #doConfigure(const File&, log4cxx::spi::LoggerRepositoryPtr&)
      for the expected format.
      */
      void doConfigure(helpers::Properties& properties,
         spi::LoggerRepositoryPtr& hierarchy);

// --------------------------------------------------------------------------
// Internal stuff
// --------------------------------------------------------------------------
protected:
      /**
      Check the provided <code>Properties</code> object for a
      #loggerFactory
      entry specified by LOGGER_FACTORY_KEY.  If such an entry
      exists, an attempt is made to create an instance using the default
      constructor.  This instance is used for subsequent Logger creations
      within this configurator.
      @see #parseCatsAndRenderers
      */
      void configureLoggerFactory(helpers::Properties& props);

      void configureRootLogger(helpers::Properties& props,
         spi::LoggerRepositoryPtr& hierarchy);

      /**
      Parse non-root elements, such non-root categories and renderers.
      */
      void parseCatsAndRenderers(helpers::Properties& props,
         spi::LoggerRepositoryPtr& hierarchy);

      /**
      Parse the additivity option for a non-root logger.
      */
      void parseAdditivityForLogger(helpers::Properties& props,
         LoggerPtr& cat, const LogString& loggerName);

      /**
      This method must work for the root logger as well.
      */
      void parseLogger(
         helpers::Properties& props, LoggerPtr& logger,
         const LogString& optionKey, const LogString& loggerName,
         const LogString& value);

      AppenderPtr parseAppender(
         helpers::Properties& props, const LogString& appenderName);

      void registryPut(const AppenderPtr& appender);
      AppenderPtr registryGet(const LogString& name);

private:
      PropertyConfigurator(const PropertyConfigurator&);
      PropertyConfigurator& operator=(const PropertyConfigurator&);
	  static PropertyWatchdog *pdog;
   }; // class PropertyConfigurator
}  // namespace log4cxx

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


#endif //_LOG4CXX_PROPERTY_CONFIGURATOR_H
