Author: ihabunek
Date: Tue Dec 13 14:30:50 2011
New Revision: 1213710

URL: http://svn.apache.org/viewvc?rev=1213710&view=rev
Log:
Reintroduced the possibility of using a custom configurator which was lost when 
rewriting the configurator (LOG4PHP-152). Also updated docs for configuration.

Added:
    
logging/log4php/trunk/src/main/php/configurators/LoggerConfiguratorDefault.php
Modified:
    logging/log4php/trunk/src/main/php/Logger.php
    logging/log4php/trunk/src/main/php/LoggerConfigurator.php
    logging/log4php/trunk/src/site/xdoc/docs/configuration.xml
    logging/log4php/trunk/src/test/php/LoggerConfiguratorTest.php
    logging/log4php/trunk/src/test/php/filters/LoggerFilterDenyAllTest.php

Modified: logging/log4php/trunk/src/main/php/Logger.php
URL: 
http://svn.apache.org/viewvc/logging/log4php/trunk/src/main/php/Logger.php?rev=1213710&r1=1213709&r2=1213710&view=diff
==============================================================================
--- logging/log4php/trunk/src/main/php/Logger.php (original)
+++ logging/log4php/trunk/src/main/php/Logger.php Tue Dec 13 14:30:50 2011
@@ -54,6 +54,7 @@ class Logger {
                'LoggerReflectionUtils' => '/LoggerReflectionUtils.php',
                'LoggerConfigurable' => '/LoggerConfigurable.php',
                'LoggerConfigurator' => '/LoggerConfigurator.php',
+               'LoggerConfiguratorDefault' => 
'/configurators/LoggerConfiguratorDefault.php',
                'LoggerConfigurationAdapter' => 
'/configurators/LoggerConfigurationAdapter.php',
                'LoggerConfigurationAdapterINI' => 
'/configurators/LoggerConfigurationAdapterINI.php',
                'LoggerConfigurationAdapterXML' => 
'/configurators/LoggerConfigurationAdapterXML.php',
@@ -558,15 +559,46 @@ class Logger {
         *
         * @param string|array $configuration Either a path to the configuration
         *   file, or a configuration array.
+        *   
+        * @param mixed $configuratorClass A custom configurator class: either 
a 
+        * class name (string), or an object which implements LoggerConfigurator
+        * interface. If left empty, the default configurator will be used. 
         */
-       public static function configure($configuration = null) {
+       public static function configure($configuration = null, 
$configuratorClass = null) {
                self::resetConfiguration();
-               $configurator = new LoggerConfigurator();
+               $configurator = self::getConfigurator($configuratorClass);
                $configurator->configure(self::getHierarchy(), $configuration);
                self::$initialized = true;
        }
        
        /**
+        * Creates a logger configurator instance based on the provided 
+        * configurator class. If no class is given, returns an instance of
+        * the default configurator.
+        * 
+        * @param string $configuratorClass The configurator class.
+        */
+       private static function getConfigurator($configuratorClass = null) {
+               if (empty($configuratorClass)) {
+                       return new LoggerConfiguratorDefault();
+               }
+               
+               if (!class_exists($configuratorClass)) {
+                       $this->warn("Specified configurator class 
[$configuratorClass] does not exist. Reverting to default configurator.");
+                       return new LoggerConfiguratorDefault();
+               }
+               
+               $configurator = new $configuratorClass();
+                       
+               if (!($configurator instanceof LoggerConfigurator)) {
+                       $this->warn("Specified configurator class 
[$configuratorClass] does not implement the LoggerConfigurator interface. 
Reverting to default configurator.");
+                       return new LoggerConfiguratorDefault();
+               }
+               
+               return $configurator;
+       }
+       
+       /**
         * Returns true if the log4php framework has been initialized.
         * @return boolean 
         */

Modified: logging/log4php/trunk/src/main/php/LoggerConfigurator.php
URL: 
http://svn.apache.org/viewvc/logging/log4php/trunk/src/main/php/LoggerConfigurator.php?rev=1213710&r1=1213709&r2=1213710&view=diff
==============================================================================
--- logging/log4php/trunk/src/main/php/LoggerConfigurator.php (original)
+++ logging/log4php/trunk/src/main/php/LoggerConfigurator.php Tue Dec 13 
14:30:50 2011
@@ -19,465 +19,24 @@
  */
 
 /**
- * Configures log4php based on a provided configuration file or array.
+ * Interface for logger configurators.
  * 
  * @package log4php
  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 
2.0
  * @version $Revision$
  * @since 2.2
  */
-class LoggerConfigurator
+interface LoggerConfigurator
 {
-       /** XML configuration file format. */
-       const FORMAT_XML = 'xml';
-       
-       /** PHP configuration file format. */
-       const FORMAT_PHP = 'php';
-       
-       /** INI (properties) configuration file format. */
-       const FORMAT_INI = 'ini';
-
-       /** Defines which adapter should be used for parsing which format. */
-       private $adapters = array(
-               self::FORMAT_XML => 'LoggerConfigurationAdapterXML',
-               self::FORMAT_INI => 'LoggerConfigurationAdapterINI',
-               self::FORMAT_PHP => 'LoggerConfigurationAdapterPHP',
-       );
-       
-       /** Default configuration; used if no configuration file is provided. */
-       private static $defaultConfiguration = array(
-        'threshold' => 'ALL',
-        'rootLogger' => array(
-            'level' => 'DEBUG',
-            'appenders' => array('default'),
-        ),
-        'appenders' => array(
-            'default' => array(
-                'class' => 'LoggerAppenderEcho',
-                'layout' => array(
-                    'class' => 'LoggerLayoutTTCC',
-                ),
-            ),
-        ),
-       );
-       
-       /** Holds the appenders before they are linked to loggers. */
-       private $appenders = array();
-       
        /**
-        * Configures log4php based on the given configuration. The input can 
-        * either be a path to the config file, or a PHP array holding the 
-        * configuration. 
+        * Configures log4php based on the given configuration. 
         * 
-        * If no configuration is given, or if the given configuration cannot be
-        * parsed for whatever reason, a warning will be issued, and log4php
-        * will use the default configuration contained in 
-        * {@link $defaultConfiguration}.
+        * All configurators implementations must implement this interface.
         * 
         * @param LoggerHierarchy $hierarchy The hierarchy on which to perform 
         *              the configuration. 
-        * @param string|array $input Either path to the config file or the 
-        *              configuration as an array. If not set, default 
configuration 
-        *              will be used.
-        */
-       public function configure(LoggerHierarchy $hierarchy, $input = null) {
-               $config = $this->parse($input);
-               $this->doConfigure($hierarchy, $config);
-       }
-       
-       /**
-        * Parses the given configuration and returns the parsed configuration
-        * as a PHP array. Does not perform any configuration. 
-        * 
-        * If no configuration is given, or if the given configuration cannot be
-        * parsed for whatever reason, a warning will be issued, and the 
default 
-        * configuration will be returned ({@link $defaultConfiguration}).
-        * 
-        * @param string|array $input Either path to the config file or the 
-        *              configuration as an array. If not set, default 
configuration 
-        *              will be used.
-        * @return array The parsed configuration.
-        */
-       public function parse($input)
-       {
-               // No input - use default configuration
-               if (!isset($input)) {
-                       $config = self::$defaultConfiguration;
-               }
-               
-               // Array input - contains configuration within the array
-               else if (is_array($input)) {
-                       $config = $input;
-               }
-               
-               // String input - contains path to configuration file
-               else if (is_string($input)) {
-                       try {
-                               $config = $this->parseFile($input);
-                       } catch (LoggerException $e) {
-                               $this->warn("Configuration failed. " . 
$e->getMessage() . " Using default configuration.");
-                               $config = self::$defaultConfiguration;
-                       }
-               }
-               
-               // Anything else is an error
-               else {
-                       $this->warn("Invalid configuration param given. 
Reverting to default configuration.");
-                       $config = self::$defaultConfiguration;
-               }
-               
-               return $config;
-       }
-
-       /** 
-        * Returns the default log4php configuration.
-        * @return array
-        */
-       public static function getDefaultConfiguration() {
-               return self::$defaultConfiguration;
-       } 
-       
-       /**
-        * Loads the configuration file from the given URL, determines which
-        * adapter to use, converts the configuration to a PHP array and
-        * returns it.
-        *
-        * @param string $url Path to the config file.
-        * @return The configuration from the config file, as a PHP array.
-        * @throws LoggerException If the configuration file cannot be loaded, 
or
-        *              if the parsing fails.
-        */
-       private function parseFile($url) {
-               
-               if (!file_exists($url)) {
-                       throw new LoggerException("File not found at [$url].");
-               }
-               
-               $type = $this->getConfigType($url);
-               $adapterClass = $this->adapters[$type];
-
-               $adapter = new $adapterClass();
-               return $adapter->convert($url);
-       }
-       
-       /** Determines configuration file type based on the file extension. */
-       private function getConfigType($url) {
-               $info = pathinfo($url);
-               $ext = strtolower($info['extension']);
-               
-               switch($ext) {
-                       case 'xml':
-                               return self::FORMAT_XML;
-                       
-                       case 'ini':
-                       case 'properties':
-                               return self::FORMAT_INI;
-                       
-                       case 'php':
-                               return self::FORMAT_PHP;
-                               
-                       default:
-                               throw new LoggerException("Unsupported 
configuration file extension: $ext");
-               }
-       }
-       
-       /**
-        * Constructs the logger hierarchy based on configuration.
-        * 
-        * @param LoggerHierarchy $hierarchy
-        * @param array $config
-        */
-       private function doConfigure(LoggerHierarchy $hierarchy, $config) {
-               if (isset($config['threshold'])) {
-                       $threshold = LoggerLevel::toLevel($config['threshold']);
-                       if (isset($threshold)) {
-                               $hierarchy->setThreshold($threshold);
-                       } else {
-                               $this->warn("Invalid threshold value 
[{$config['threshold']}] specified. Ignoring threshold definition.");
-                       }
-               }
-               
-               // Configure appenders and add them to the appender pool
-               if (isset($config['appenders']) && 
is_array($config['appenders'])) {
-                       foreach($config['appenders'] as $name => 
$appenderConfig) {
-                               $this->configureAppender($name, 
$appenderConfig);
-                       }
-               }
-               
-               // Configure root logger 
-               if (isset($config['rootLogger'])) {
-                       $this->configureRootLogger($hierarchy, 
$config['rootLogger']);
-               }
-               
-               // Configure loggers
-               if (isset($config['loggers']) && is_array($config['loggers'])) {
-                       foreach($config['loggers'] as $loggerName => 
$loggerConfig) {
-                               $this->configureOtherLogger($hierarchy, 
$loggerName, $loggerConfig);
-                       }
-               }
-
-               // Configure renderers
-               if (isset($config['renderers']) && 
is_array($config['renderers'])) {
-                       foreach($config['renderers'] as $rendererConfig) {
-                               $this->configureRenderer($hierarchy, 
$rendererConfig);
-                       }
-               }
-       }
-       
-       private function configureRenderer(LoggerHierarchy $hierarchy, $config) 
{
-               if (!isset($config['renderingClass'])) {
-                       $this->warn("Rendering class not specified. Skipping 
renderers definition.");
-                       return;                 
-               }
-               
-               $renderingClass = $config['renderingClass'];
-               if (!class_exists($renderingClass)) {
-                       $this->warn("Nonexistant rendering class 
[$renderingClass] specified. Skipping renderers definition.");
-                       return;
-               }
-               
-               $renderingClassInstance = new $renderingClass();
-               if (!$renderingClassInstance instanceof LoggerRendererObject) {
-                       $this->warn("Invalid class [$renderingClass] given. Not 
a valid LoggerRenderer class. Skipping renderers definition.");
-                       return;                 
-               }
-       
-               if (!isset($config['renderedClass'])) {
-                       $this->warn("Rendered class not specified for rendering 
Class [$renderingClass]. Skipping renderers definition.");
-                       return;                 
-               }
-               
-               $renderedClass = $config['renderedClass'];
-               if (!class_exists($renderedClass)) {
-                       $this->warn("Nonexistant rendered class 
[$renderedClass] specified for renderer [$renderingClass]. Skipping renderers 
definition.");
-                       return;
-               }               
-
-               $hierarchy->getRendererMap()->addRenderer($renderedClass, 
$renderingClassInstance);
-       }
-       
-       /** 
-        * Configures an appender based on given config and saves it to 
-        * {@link $appenders} array so it can be later linked to loggers. 
-        * @param string $name Appender name. 
-        * @param array $config Appender configuration options.
-        */
-       private function configureAppender($name, $config) {
-
-               // TODO: add this check to other places where it might be useful
-               if (!is_array($config)) {
-                       $type = gettype($config);
-                       $this->warn("Invalid configuration provided for 
appender [$name]. Expected an array, found <$type>. Skipping appender 
definition.");
-                       return;
-               }
-               
-               // Parse appender class
-               $class = $config['class'];
-               if (empty($class)) {
-                       $this->warn("No class given for appender [$name]. 
Skipping appender definition.");
-                       return;
-               }
-               if (!class_exists($class)) {
-                       $this->warn("Invalid class [$class] given for appender 
[$name]. Class does not exist. Skipping appender definition.");
-                       return;
-               }
-               
-               // Instantiate the appender
-               $appender = new $class($name);
-               if (!($appender instanceof LoggerAppender)) {
-                       $this->warn("Invalid class [$class] given for appender 
[$name]. Not a valid LoggerAppender class. Skipping appender definition.");
-                       return;
-               }
-               
-               // Parse the appender threshold
-               if (isset($config['threshold'])) {
-                       $threshold = LoggerLevel::toLevel($config['threshold']);
-                       if ($threshold instanceof LoggerLevel) {
-                               $appender->setThreshold($threshold);
-                       } else {
-                               $this->warn("Invalid threshold value 
[{$config['threshold']}] specified for appender [$name]. Ignoring threshold 
definition.");
-                       }
-               }
-               
-               // Parse the appender layout
-               if ($appender->requiresLayout() && isset($config['layout'])) {
-                       $this->createAppenderLayout($appender, 
$config['layout']);
-               }
-               
-               // Parse filters
-               if (isset($config['filters']) && is_array($config['filters'])) {
-                       foreach($config['filters'] as $filterConfig) {
-                               $this->createAppenderFilter($appender, 
$filterConfig);
-                       }
-               }
-               
-               // Set options if any
-               if (isset($config['params'])) {
-                       $this->setOptions($appender, $config['params']);
-               }
-
-               // Activate and save for later linking to loggers
-               $appender->activateOptions();
-               $this->appenders[$name] = $appender;
-       }
-       
-       /**
-        * Parses layout config, creates the layout and links it to the 
appender.
-        * @param LoggerAppender $appender
-        * @param array $config Layout configuration.
-        */
-       private function createAppenderLayout(LoggerAppender $appender, 
$config) {
-               $name = $appender->getName();
-               $class = $config['class'];
-               if (empty($class)) {
-                       $this->warn("Layout class not specified for appender 
[$name]. Reverting to default layout.");
-                       return;
-               }
-               if (!class_exists($class)) {
-                       $this->warn("Nonexistant layout class [$class] 
specified for appender [$name]. Reverting to default layout.");
-                       return;
-               }
-               
-               $layout = new $class();
-               if (!($layout instanceof LoggerLayout)) {
-                       $this->warn("Invalid layout class [$class] sepcified 
for appender [$name]. Reverting to default layout.");
-                       return;
-               }
-               
-               if (isset($config['params'])) {
-                       $this->setOptions($layout, $config['params']);
-               }
-               
-               $layout->activateOptions();
-               $appender->setLayout($layout);
-       }
-       
-       /**
-        * Parses filter config, creates the filter and adds it to the 
appender's 
-        * filter chain.
-        * @param LoggerAppender $appender
-        * @param array $config Filter configuration.
-        */
-       private function createAppenderFilter(LoggerAppender $appender, 
$config) {
-               $name = $appender->getName();
-               $class = $config['class'];
-               if (!class_exists($class)) {
-                       $this->warn("Nonexistant filter class [$class] 
specified on appender [$name]. Skipping filter definition.");
-                       return;
-               }
-       
-               $filter = new $class();
-               if (!($filter instanceof LoggerFilter)) {
-                       $this->warn("Invalid filter class [$class] sepcified on 
appender [$name]. Skipping filter definition.");
-                       return;
-               }
-       
-               if (isset($config['params'])) {
-                       $this->setOptions($filter, $config['params']);
-               }
-       
-               $filter->activateOptions();
-               $appender->addFilter($filter);
-       }
-       
-       /** 
-        * Configures the root logger
-        * @see configureLogger() 
-        */
-       private function configureRootLogger(LoggerHierarchy $hierarchy, 
$config) {
-               $logger = $hierarchy->getRootLogger();
-               $this->configureLogger($logger, $config);
-       }
-
-       /**
-        * Configures a logger which is not root.
-        * @see configureLogger()
-        */
-       private function configureOtherLogger(LoggerHierarchy $hierarchy, 
$name, $config) {
-               // Get logger from hierarchy (this creates it if it doesn't 
already exist)
-               $logger = $hierarchy->getLogger($name);
-               $this->configureLogger($logger, $config);
-       }
-       
-       /**
-        * Configures a logger. 
-        * 
-        * @param Logger $logger The logger to configure
-        * @param array $config Logger configuration options.
-        */
-       private function configureLogger(Logger $logger, $config) {
-               $loggerName = $logger->getName();
-               
-               // Set logger level
-               if (isset($config['level'])) {
-                       $level = LoggerLevel::toLevel($config['level']);
-                       if (isset($level)) {
-                               $logger->setLevel($level);
-                       } else {
-                               $default = $logger->getLevel();
-                               $this->warn("Invalid level value 
[{$config['level']}] specified for logger [$loggerName]. Ignoring level 
definition.");
-                       }
-               }
-               
-               // Link appenders to logger
-               if (isset($config['appenders'])) {
-                       foreach($config['appenders'] as $appenderName) {
-                               if (isset($this->appenders[$appenderName])) {
-                                       
$logger->addAppender($this->appenders[$appenderName]);
-                               } else {
-                                       $this->warn("Nonexistnant appender 
[$appenderName] linked to logger [$loggerName].");
-                               }
-                       }
-               }
-               
-               // Set logger additivity
-               if (isset($config['additivity'])) {
-                       $additivity = 
LoggerOptionConverter::toBoolean($config['additivity'], null);
-                       if (is_bool($additivity)) {
-                               $logger->setAdditivity($additivity);
-                       } else {
-                               $this->warn("Invalid additivity value 
[{$config['additivity']}] specified for logger [$loggerName]. Ignoring 
additivity setting.");
-                       }
-               }
-       }
-
-       /**
-        * Helper method which applies given options to an object which has 
setters
-        * for these options (such as appenders, layouts, etc.).
-        * 
-        * For example, if options are:
-        * <code>
-        * array(
-        *      'file' => '/tmp/myfile.log',
-        *      'append' => true
-        * )
-        * </code>
-        * 
-        * This method will call:
-        * <code>
-        * $object->setFile('/tmp/myfile.log')
-        * $object->setAppend(true)
-        * </code>
-        * 
-        * If required setters do not exist, it will produce a warning. 
-        * 
-        * @param mixed $object The object to configure.
-        * @param unknown_type $options
+        * @param mixed $input Either path to the config file or the 
+        *              configuration as an array.
         */
-       private function setOptions($object, $options) {
-               foreach($options as $name => $value) {
-                       $setter = "set$name";
-                       if (method_exists($object, $setter)) {
-                               $object->$setter($value);
-                       } else {
-                               $class = get_class($object);
-                               $this->warn("Nonexistant option [$name] 
specified on [$class]. Skipping.");
-                       }
-               }
-       }
-       
-       /** Helper method to simplify error reporting. */
-       private function warn($message) {
-               trigger_error("log4php: $message", E_USER_WARNING);
-       }
+       public function configure(LoggerHierarchy $hierarchy, $input = null);
 }
\ No newline at end of file

Added: 
logging/log4php/trunk/src/main/php/configurators/LoggerConfiguratorDefault.php
URL: 
http://svn.apache.org/viewvc/logging/log4php/trunk/src/main/php/configurators/LoggerConfiguratorDefault.php?rev=1213710&view=auto
==============================================================================
--- 
logging/log4php/trunk/src/main/php/configurators/LoggerConfiguratorDefault.php 
(added)
+++ 
logging/log4php/trunk/src/main/php/configurators/LoggerConfiguratorDefault.php 
Tue Dec 13 14:30:50 2011
@@ -0,0 +1,485 @@
+<?php
+/**
+ * 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.
+ *
+ * @package log4php
+ */
+
+/**
+ * Default implementation of the logger configurator.
+ * 
+ * Configures log4php based on a provided configuration file or array.
+ * 
+ * @package log4php
+ * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 
2.0
+ * @version $Revision: 1212319 $
+ * @since 2.2
+ */
+class LoggerConfiguratorDefault implements LoggerConfigurator
+{
+       /** XML configuration file format. */
+       const FORMAT_XML = 'xml';
+       
+       /** PHP configuration file format. */
+       const FORMAT_PHP = 'php';
+       
+       /** INI (properties) configuration file format. */
+       const FORMAT_INI = 'ini';
+
+       /** Defines which adapter should be used for parsing which format. */
+       private $adapters = array(
+               self::FORMAT_XML => 'LoggerConfigurationAdapterXML',
+               self::FORMAT_INI => 'LoggerConfigurationAdapterINI',
+               self::FORMAT_PHP => 'LoggerConfigurationAdapterPHP',
+       );
+       
+       /** Default configuration; used if no configuration file is provided. */
+       private static $defaultConfiguration = array(
+        'threshold' => 'ALL',
+        'rootLogger' => array(
+            'level' => 'DEBUG',
+            'appenders' => array('default'),
+        ),
+        'appenders' => array(
+            'default' => array(
+                'class' => 'LoggerAppenderEcho',
+                'layout' => array(
+                    'class' => 'LoggerLayoutTTCC',
+                ),
+            ),
+        ),
+       );
+       
+       /** Holds the appenders before they are linked to loggers. */
+       private $appenders = array();
+       
+       /**
+        * Configures log4php based on the given configuration. The input can 
+        * either be a path to the config file, or a PHP array holding the 
+        * configuration. 
+        * 
+        * If no configuration is given, or if the given configuration cannot be
+        * parsed for whatever reason, a warning will be issued, and log4php
+        * will use the default configuration contained in 
+        * {@link $defaultConfiguration}.
+        * 
+        * @param LoggerHierarchy $hierarchy The hierarchy on which to perform 
+        *              the configuration. 
+        * @param string|array $input Either path to the config file or the 
+        *              configuration as an array. If not set, default 
configuration 
+        *              will be used.
+        */
+       public function configure(LoggerHierarchy $hierarchy, $input = null) {
+               $config = $this->parse($input);
+               $this->doConfigure($hierarchy, $config);
+       }
+       
+       /**
+        * Parses the given configuration and returns the parsed configuration
+        * as a PHP array. Does not perform any configuration. 
+        * 
+        * If no configuration is given, or if the given configuration cannot be
+        * parsed for whatever reason, a warning will be issued, and the 
default 
+        * configuration will be returned ({@link $defaultConfiguration}).
+        * 
+        * @param string|array $input Either path to the config file or the 
+        *              configuration as an array. If not set, default 
configuration 
+        *              will be used.
+        * @return array The parsed configuration.
+        */
+       public function parse($input)
+       {
+               // No input - use default configuration
+               if (!isset($input)) {
+                       $config = self::$defaultConfiguration;
+               }
+               
+               // Array input - contains configuration within the array
+               else if (is_array($input)) {
+                       $config = $input;
+               }
+               
+               // String input - contains path to configuration file
+               else if (is_string($input)) {
+                       try {
+                               $config = $this->parseFile($input);
+                       } catch (LoggerException $e) {
+                               $this->warn("Configuration failed. " . 
$e->getMessage() . " Using default configuration.");
+                               $config = self::$defaultConfiguration;
+                       }
+               }
+               
+               // Anything else is an error
+               else {
+                       $this->warn("Invalid configuration param given. 
Reverting to default configuration.");
+                       $config = self::$defaultConfiguration;
+               }
+               
+               return $config;
+       }
+
+       /** 
+        * Returns the default log4php configuration.
+        * @return array
+        */
+       public static function getDefaultConfiguration() {
+               return self::$defaultConfiguration;
+       } 
+       
+       /**
+        * Loads the configuration file from the given URL, determines which
+        * adapter to use, converts the configuration to a PHP array and
+        * returns it.
+        *
+        * @param string $url Path to the config file.
+        * @return The configuration from the config file, as a PHP array.
+        * @throws LoggerException If the configuration file cannot be loaded, 
or
+        *              if the parsing fails.
+        */
+       private function parseFile($url) {
+               
+               if (!file_exists($url)) {
+                       throw new LoggerException("File not found at [$url].");
+               }
+               
+               $type = $this->getConfigType($url);
+               $adapterClass = $this->adapters[$type];
+
+               $adapter = new $adapterClass();
+               return $adapter->convert($url);
+       }
+       
+       /** Determines configuration file type based on the file extension. */
+       private function getConfigType($url) {
+               $info = pathinfo($url);
+               $ext = strtolower($info['extension']);
+               
+               switch($ext) {
+                       case 'xml':
+                               return self::FORMAT_XML;
+                       
+                       case 'ini':
+                       case 'properties':
+                               return self::FORMAT_INI;
+                       
+                       case 'php':
+                               return self::FORMAT_PHP;
+                               
+                       default:
+                               throw new LoggerException("Unsupported 
configuration file extension: $ext");
+               }
+       }
+       
+       /**
+        * Constructs the logger hierarchy based on configuration.
+        * 
+        * @param LoggerHierarchy $hierarchy
+        * @param array $config
+        */
+       private function doConfigure(LoggerHierarchy $hierarchy, $config) {
+               if (isset($config['threshold'])) {
+                       $threshold = LoggerLevel::toLevel($config['threshold']);
+                       if (isset($threshold)) {
+                               $hierarchy->setThreshold($threshold);
+                       } else {
+                               $this->warn("Invalid threshold value 
[{$config['threshold']}] specified. Ignoring threshold definition.");
+                       }
+               }
+               
+               // Configure appenders and add them to the appender pool
+               if (isset($config['appenders']) && 
is_array($config['appenders'])) {
+                       foreach($config['appenders'] as $name => 
$appenderConfig) {
+                               $this->configureAppender($name, 
$appenderConfig);
+                       }
+               }
+               
+               // Configure root logger 
+               if (isset($config['rootLogger'])) {
+                       $this->configureRootLogger($hierarchy, 
$config['rootLogger']);
+               }
+               
+               // Configure loggers
+               if (isset($config['loggers']) && is_array($config['loggers'])) {
+                       foreach($config['loggers'] as $loggerName => 
$loggerConfig) {
+                               $this->configureOtherLogger($hierarchy, 
$loggerName, $loggerConfig);
+                       }
+               }
+
+               // Configure renderers
+               if (isset($config['renderers']) && 
is_array($config['renderers'])) {
+                       foreach($config['renderers'] as $rendererConfig) {
+                               $this->configureRenderer($hierarchy, 
$rendererConfig);
+                       }
+               }
+       }
+       
+       private function configureRenderer(LoggerHierarchy $hierarchy, $config) 
{
+               if (!isset($config['renderingClass'])) {
+                       $this->warn("Rendering class not specified. Skipping 
renderers definition.");
+                       return;                 
+               }
+               
+               $renderingClass = $config['renderingClass'];
+               if (!class_exists($renderingClass)) {
+                       $this->warn("Nonexistant rendering class 
[$renderingClass] specified. Skipping renderers definition.");
+                       return;
+               }
+               
+               $renderingClassInstance = new $renderingClass();
+               if (!$renderingClassInstance instanceof LoggerRendererObject) {
+                       $this->warn("Invalid class [$renderingClass] given. Not 
a valid LoggerRenderer class. Skipping renderers definition.");
+                       return;                 
+               }
+       
+               if (!isset($config['renderedClass'])) {
+                       $this->warn("Rendered class not specified for rendering 
Class [$renderingClass]. Skipping renderers definition.");
+                       return;                 
+               }
+               
+               $renderedClass = $config['renderedClass'];
+               if (!class_exists($renderedClass)) {
+                       $this->warn("Nonexistant rendered class 
[$renderedClass] specified for renderer [$renderingClass]. Skipping renderers 
definition.");
+                       return;
+               }               
+
+               $hierarchy->getRendererMap()->addRenderer($renderedClass, 
$renderingClassInstance);
+       }
+       
+       /** 
+        * Configures an appender based on given config and saves it to 
+        * {@link $appenders} array so it can be later linked to loggers. 
+        * @param string $name Appender name. 
+        * @param array $config Appender configuration options.
+        */
+       private function configureAppender($name, $config) {
+
+               // TODO: add this check to other places where it might be useful
+               if (!is_array($config)) {
+                       $type = gettype($config);
+                       $this->warn("Invalid configuration provided for 
appender [$name]. Expected an array, found <$type>. Skipping appender 
definition.");
+                       return;
+               }
+               
+               // Parse appender class
+               $class = $config['class'];
+               if (empty($class)) {
+                       $this->warn("No class given for appender [$name]. 
Skipping appender definition.");
+                       return;
+               }
+               if (!class_exists($class)) {
+                       $this->warn("Invalid class [$class] given for appender 
[$name]. Class does not exist. Skipping appender definition.");
+                       return;
+               }
+               
+               // Instantiate the appender
+               $appender = new $class($name);
+               if (!($appender instanceof LoggerAppender)) {
+                       $this->warn("Invalid class [$class] given for appender 
[$name]. Not a valid LoggerAppender class. Skipping appender definition.");
+                       return;
+               }
+               
+               // Parse the appender threshold
+               if (isset($config['threshold'])) {
+                       $threshold = LoggerLevel::toLevel($config['threshold']);
+                       if ($threshold instanceof LoggerLevel) {
+                               $appender->setThreshold($threshold);
+                       } else {
+                               $this->warn("Invalid threshold value 
[{$config['threshold']}] specified for appender [$name]. Ignoring threshold 
definition.");
+                       }
+               }
+               
+               // Parse the appender layout
+               if ($appender->requiresLayout() && isset($config['layout'])) {
+                       $this->createAppenderLayout($appender, 
$config['layout']);
+               }
+               
+               // Parse filters
+               if (isset($config['filters']) && is_array($config['filters'])) {
+                       foreach($config['filters'] as $filterConfig) {
+                               $this->createAppenderFilter($appender, 
$filterConfig);
+                       }
+               }
+               
+               // Set options if any
+               if (isset($config['params'])) {
+                       $this->setOptions($appender, $config['params']);
+               }
+
+               // Activate and save for later linking to loggers
+               $appender->activateOptions();
+               $this->appenders[$name] = $appender;
+       }
+       
+       /**
+        * Parses layout config, creates the layout and links it to the 
appender.
+        * @param LoggerAppender $appender
+        * @param array $config Layout configuration.
+        */
+       private function createAppenderLayout(LoggerAppender $appender, 
$config) {
+               $name = $appender->getName();
+               $class = $config['class'];
+               if (empty($class)) {
+                       $this->warn("Layout class not specified for appender 
[$name]. Reverting to default layout.");
+                       return;
+               }
+               if (!class_exists($class)) {
+                       $this->warn("Nonexistant layout class [$class] 
specified for appender [$name]. Reverting to default layout.");
+                       return;
+               }
+               
+               $layout = new $class();
+               if (!($layout instanceof LoggerLayout)) {
+                       $this->warn("Invalid layout class [$class] sepcified 
for appender [$name]. Reverting to default layout.");
+                       return;
+               }
+               
+               if (isset($config['params'])) {
+                       $this->setOptions($layout, $config['params']);
+               }
+               
+               $layout->activateOptions();
+               $appender->setLayout($layout);
+       }
+       
+       /**
+        * Parses filter config, creates the filter and adds it to the 
appender's 
+        * filter chain.
+        * @param LoggerAppender $appender
+        * @param array $config Filter configuration.
+        */
+       private function createAppenderFilter(LoggerAppender $appender, 
$config) {
+               $name = $appender->getName();
+               $class = $config['class'];
+               if (!class_exists($class)) {
+                       $this->warn("Nonexistant filter class [$class] 
specified on appender [$name]. Skipping filter definition.");
+                       return;
+               }
+       
+               $filter = new $class();
+               if (!($filter instanceof LoggerFilter)) {
+                       $this->warn("Invalid filter class [$class] sepcified on 
appender [$name]. Skipping filter definition.");
+                       return;
+               }
+       
+               if (isset($config['params'])) {
+                       $this->setOptions($filter, $config['params']);
+               }
+       
+               $filter->activateOptions();
+               $appender->addFilter($filter);
+       }
+       
+       /** 
+        * Configures the root logger
+        * @see configureLogger() 
+        */
+       private function configureRootLogger(LoggerHierarchy $hierarchy, 
$config) {
+               $logger = $hierarchy->getRootLogger();
+               $this->configureLogger($logger, $config);
+       }
+
+       /**
+        * Configures a logger which is not root.
+        * @see configureLogger()
+        */
+       private function configureOtherLogger(LoggerHierarchy $hierarchy, 
$name, $config) {
+               // Get logger from hierarchy (this creates it if it doesn't 
already exist)
+               $logger = $hierarchy->getLogger($name);
+               $this->configureLogger($logger, $config);
+       }
+       
+       /**
+        * Configures a logger. 
+        * 
+        * @param Logger $logger The logger to configure
+        * @param array $config Logger configuration options.
+        */
+       private function configureLogger(Logger $logger, $config) {
+               $loggerName = $logger->getName();
+               
+               // Set logger level
+               if (isset($config['level'])) {
+                       $level = LoggerLevel::toLevel($config['level']);
+                       if (isset($level)) {
+                               $logger->setLevel($level);
+                       } else {
+                               $default = $logger->getLevel();
+                               $this->warn("Invalid level value 
[{$config['level']}] specified for logger [$loggerName]. Ignoring level 
definition.");
+                       }
+               }
+               
+               // Link appenders to logger
+               if (isset($config['appenders'])) {
+                       foreach($config['appenders'] as $appenderName) {
+                               if (isset($this->appenders[$appenderName])) {
+                                       
$logger->addAppender($this->appenders[$appenderName]);
+                               } else {
+                                       $this->warn("Nonexistnant appender 
[$appenderName] linked to logger [$loggerName].");
+                               }
+                       }
+               }
+               
+               // Set logger additivity
+               if (isset($config['additivity'])) {
+                       $additivity = 
LoggerOptionConverter::toBoolean($config['additivity'], null);
+                       if (is_bool($additivity)) {
+                               $logger->setAdditivity($additivity);
+                       } else {
+                               $this->warn("Invalid additivity value 
[{$config['additivity']}] specified for logger [$loggerName]. Ignoring 
additivity setting.");
+                       }
+               }
+       }
+
+       /**
+        * Helper method which applies given options to an object which has 
setters
+        * for these options (such as appenders, layouts, etc.).
+        * 
+        * For example, if options are:
+        * <code>
+        * array(
+        *      'file' => '/tmp/myfile.log',
+        *      'append' => true
+        * )
+        * </code>
+        * 
+        * This method will call:
+        * <code>
+        * $object->setFile('/tmp/myfile.log')
+        * $object->setAppend(true)
+        * </code>
+        * 
+        * If required setters do not exist, it will produce a warning. 
+        * 
+        * @param mixed $object The object to configure.
+        * @param unknown_type $options
+        */
+       private function setOptions($object, $options) {
+               foreach($options as $name => $value) {
+                       $setter = "set$name";
+                       if (method_exists($object, $setter)) {
+                               $object->$setter($value);
+                       } else {
+                               $class = get_class($object);
+                               $this->warn("Nonexistant option [$name] 
specified on [$class]. Skipping.");
+                       }
+               }
+       }
+       
+       /** Helper method to simplify error reporting. */
+       private function warn($message) {
+               trigger_error("log4php: $message", E_USER_WARNING);
+       }
+}
\ No newline at end of file

Modified: logging/log4php/trunk/src/site/xdoc/docs/configuration.xml
URL: 
http://svn.apache.org/viewvc/logging/log4php/trunk/src/site/xdoc/docs/configuration.xml?rev=1213710&r1=1213709&r2=1213710&view=diff
==============================================================================
--- logging/log4php/trunk/src/site/xdoc/docs/configuration.xml (original)
+++ logging/log4php/trunk/src/site/xdoc/docs/configuration.xml Tue Dec 13 
14:30:50 2011
@@ -203,26 +203,70 @@ array(
 
                                <div class="alert-message block-message info">
                                        <p><strong>Hint:</strong> You can fetch 
the default configuration as a PHP array by running:</p>
-                                       <pre 
class="prettyprint">LoggerConfigurator::getDefaultConfiguration();</pre>
+                                       <pre 
class="prettyprint">LoggerConfiguratorDefault::getDefaultConfiguration();</pre>
                                </div>
                        </subsection>
                        
                        <subsection name="Programmatic configuration">
                                
-                               <p>It is possible to configure log4php fully 
programmatically. Here is an example:</p>
+                               <p>It is possible to configure log4php fully 
programmatically. This requires the user to implement 
+                               their own configurator object. Configurators 
must implement the <code>LoggerConfigurator</code> 
+                               interface.</p>
+                               
+                               <p>Here is an example:</p>
 
 <pre class="prettyprint">
+class MyConfigurator implements LoggerConfigurator {
+       
+    public function configure(LoggerHierarchy $hierarchy, $input = null) {
+
+        // Create an appender which logs to file
+        $appFile = new LoggerAppenderFile('foo');
+        $appFile->setFile('D:/Temp/log.txt');
+        $appFile->setAppend(true);
+        $appFile->setThreshold('all');
+        $appFile->activateOptions();
+        
+        // Use a different layout for the next appender
+        $layout = new LoggerLayoutTTCC();
+        $layout->setContextPrinting(false);
+        $layout->setDateFormat('%Y-%m-%d %H:%M:%S');
+        $layout->activateOptions();
+        
+        // Create an appender which echoes log events, using a custom layout
+        // and with the threshold set to INFO 
+        $appEcho = new LoggerAppenderEcho('bar');
+        $appEcho->setLayout($layout);
+        $appEcho->setThreshold('info');
+        $appEcho->activateOptions();
+        
+        // Add both appenders to the root logger
+        $root = $hierarchy->getRootLogger();
+        $root->addAppender($appFile);
+        $root->addAppender($appEcho);
+    }
+}
+</pre>
+
+                               <p>To use the configurator, pass it as a second 
parameter to <code>Logger::configure()</code> 
+                               (either the name of the class as a string or an 
instance).</p>
 
+<pre class="prettyprint">
+Logger::configure(null, 'MyConfigurator');
 
+$log = Logger::getRootLogger();
+$log->trace('one');
+$log->debug('two');
+$log->info('three');
+$log->warn('four');
+$log->error('five');
 </pre>
 
                                <div class="alert-message block-message warn">
-                                       <p>Note that named loggers should 
always be created by calling Logger::getLogger('name'). This 
-                                       will create the logger if it doesn't 
already exist and place it in the logger hierarchy.</p>
+                                       <p><strong>Note: </strong>Always call 
<code>activateOptions()</code> on all appenders, filters and layouts after 
setting
+                                       their configuration parameters. 
Otherwise, the configuration may not be properly activated.</p>
                                </div>
                        </subsection>
-
-
                </section>
        </body>
 </document>

Modified: logging/log4php/trunk/src/test/php/LoggerConfiguratorTest.php
URL: 
http://svn.apache.org/viewvc/logging/log4php/trunk/src/test/php/LoggerConfiguratorTest.php?rev=1213710&r1=1213709&r2=1213710&view=diff
==============================================================================
--- logging/log4php/trunk/src/test/php/LoggerConfiguratorTest.php (original)
+++ logging/log4php/trunk/src/test/php/LoggerConfiguratorTest.php Tue Dec 13 
14:30:50 2011
@@ -98,7 +98,7 @@
                ),
         );
 
-        $configurator = new LoggerConfigurator();
+        $configurator = new LoggerConfiguratorDefault();
         $configurator->configure($hierachyMock, $config);
        }
        

Modified: logging/log4php/trunk/src/test/php/filters/LoggerFilterDenyAllTest.php
URL: 
http://svn.apache.org/viewvc/logging/log4php/trunk/src/test/php/filters/LoggerFilterDenyAllTest.php?rev=1213710&r1=1213709&r2=1213710&view=diff
==============================================================================
--- logging/log4php/trunk/src/test/php/filters/LoggerFilterDenyAllTest.php 
(original)
+++ logging/log4php/trunk/src/test/php/filters/LoggerFilterDenyAllTest.php Tue 
Dec 13 14:30:50 2011
@@ -47,7 +47,7 @@ class LoggerFilterDenyAllTest extends PH
     }
     
     public function testConfiguration() {
-       $config = LoggerConfigurator::getDefaultConfiguration();
+       $config = LoggerConfiguratorDefault::getDefaultConfiguration();
        $config['appenders']['default']['filters'] = array(
                array(
                        'class' => 'LoggerFilterDenyAll'


Reply via email to