library/log4php/configurators/LoggerConfigurationAdapterINI.php
changeset 46 f11c31f7fa3e
parent 45 a56e7f9a0463
child 47 03388ec805b4
equal deleted inserted replaced
45:a56e7f9a0463 46:f11c31f7fa3e
     1 <?php
       
     2 /**
       
     3  * Licensed to the Apache Software Foundation (ASF) under one or more
       
     4  * contributor license agreements. See the NOTICE file distributed with
       
     5  * this work for additional information regarding copyright ownership.
       
     6  * The ASF licenses this file to You under the Apache License, Version 2.0
       
     7  * (the "License"); you may not use this file except in compliance with
       
     8  * the License. You may obtain a copy of the License at
       
     9  *
       
    10  *     http://www.apache.org/licenses/LICENSE-2.0
       
    11  *
       
    12  * Unless required by applicable law or agreed to in writing, software
       
    13  * distributed under the License is distributed on an "AS IS" BASIS,
       
    14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
       
    15  * See the License for the specific language governing permissions and
       
    16  * limitations under the License.
       
    17  *
       
    18  * @package log4php
       
    19  */
       
    20 
       
    21 /**
       
    22  * Converts ini configuration files to a PHP array.
       
    23  *
       
    24  * These used to be called "properties" files (inherited from log4j), and that
       
    25  * file extension is still supported.
       
    26  *
       
    27  * @package log4php
       
    28  * @subpackage configurators
       
    29  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
       
    30  * @version $Revision: 1343601 $
       
    31  * @since 2.2
       
    32  */
       
    33 class LoggerConfigurationAdapterINI implements LoggerConfigurationAdapter {
       
    34 
       
    35     /** Name to assign to the root logger. */
       
    36     const ROOT_LOGGER_NAME = "root";
       
    37 
       
    38     /** Prefix used for defining logger additivity. */
       
    39     const ADDITIVITY_PREFIX = "log4php.additivity.";
       
    40 
       
    41     /** Prefix used for defining logger threshold. */
       
    42     const THRESHOLD_PREFIX = "log4php.threshold";
       
    43 
       
    44     /** Prefix used for defining the root logger. */
       
    45     const ROOT_LOGGER_PREFIX = "log4php.rootLogger";
       
    46 
       
    47     /** Prefix used for defining a logger. */
       
    48     const LOGGER_PREFIX = "log4php.logger.";
       
    49 
       
    50     /** Prefix used for defining an appender. */
       
    51     const APPENDER_PREFIX = "log4php.appender.";
       
    52 
       
    53     /** Prefix used for defining a renderer. */
       
    54     const RENDERER_PREFIX = "log4php.renderer.";
       
    55 
       
    56     /** Holds the configuration. */
       
    57     private $config = array();
       
    58 
       
    59     /**
       
    60      * Loads and parses the INI configuration file.
       
    61      *
       
    62      * @param string $url Path to the config file.
       
    63      * @throws LoggerException
       
    64      */
       
    65     private function load($url) {
       
    66         if (!file_exists($url)) {
       
    67             throw new LoggerException("File [$url] does not exist.");
       
    68         }
       
    69 
       
    70         $properties = @parse_ini_file($url, true);
       
    71         if ($properties === false) {
       
    72             $error = error_get_last();
       
    73             throw new LoggerException("Error parsing configuration file: {$error['message']}");
       
    74         }
       
    75 
       
    76         return $properties;
       
    77     }
       
    78 
       
    79     /**
       
    80      * Converts the provided INI configuration file to a PHP array config.
       
    81      *
       
    82      * @param string $path Path to the config file.
       
    83      * @throws LoggerException If the file cannot be loaded or parsed.
       
    84      */
       
    85     public function convert($path) {
       
    86         // Load the configuration
       
    87         $properties = $this->load($path);
       
    88 
       
    89         // Parse threshold
       
    90         if (isset($properties[self::THRESHOLD_PREFIX])) {
       
    91             $this->config['threshold'] = $properties[self::THRESHOLD_PREFIX];
       
    92         }
       
    93 
       
    94         // Parse root logger
       
    95         if (isset($properties[self::ROOT_LOGGER_PREFIX])) {
       
    96             $this->parseLogger($properties[self::ROOT_LOGGER_PREFIX], self::ROOT_LOGGER_NAME);
       
    97         }
       
    98 
       
    99         $appenders = array();
       
   100 
       
   101         foreach ($properties as $key => $value) {
       
   102             // Parse loggers
       
   103             if ($this->beginsWith($key, self::LOGGER_PREFIX)) {
       
   104                 $name = substr($key, strlen(self::LOGGER_PREFIX));
       
   105                 $this->parseLogger($value, $name);
       
   106             }
       
   107 
       
   108             // Parse additivity
       
   109             if ($this->beginsWith($key, self::ADDITIVITY_PREFIX)) {
       
   110                 $name = substr($key, strlen(self::ADDITIVITY_PREFIX));
       
   111                 $this->config['loggers'][$name]['additivity'] = $value;
       
   112             } // Parse appenders
       
   113             else if ($this->beginsWith($key, self::APPENDER_PREFIX)) {
       
   114                 $this->parseAppender($key, $value);
       
   115             } // Parse renderers
       
   116             else if ($this->beginsWith($key, self::RENDERER_PREFIX)) {
       
   117                 $this->parseRenderer($key, $value);
       
   118             }
       
   119         }
       
   120 
       
   121         return $this->config;
       
   122     }
       
   123 
       
   124 
       
   125     /**
       
   126      * Parses a logger definition.
       
   127      *
       
   128      * Loggers are defined in the following manner:
       
   129      * <pre>
       
   130      * log4php.logger.<name> = [<level>], [<appender-ref>, <appender-ref>, ...]
       
   131      * </pre>
       
   132      *
       
   133      * @param string $value The configuration value (level and appender-refs).
       
   134      * @param string $name Logger name.
       
   135      */
       
   136     private function parseLogger($value, $name) {
       
   137         // Value is divided by commas
       
   138         $parts = explode(',', $value);
       
   139         if (empty($value) || empty($parts)) {
       
   140             return;
       
   141         }
       
   142 
       
   143         // The first value is the logger level
       
   144         $level = array_shift($parts);
       
   145 
       
   146         // The remaining values are appender references
       
   147         $appenders = array();
       
   148         while ($appender = array_shift($parts)) {
       
   149             $appender = trim($appender);
       
   150             if (!empty($appender)) {
       
   151                 $appenders[] = trim($appender);
       
   152             }
       
   153         }
       
   154 
       
   155         // Find the target configuration
       
   156         if ($name == self::ROOT_LOGGER_NAME) {
       
   157             $this->config['rootLogger']['level'] = trim($level);
       
   158             $this->config['rootLogger']['appenders'] = $appenders;
       
   159         } else {
       
   160             $this->config['loggers'][$name]['level'] = trim($level);
       
   161             $this->config['loggers'][$name]['appenders'] = $appenders;
       
   162         }
       
   163     }
       
   164 
       
   165     /**
       
   166      * Parses an configuration line pertaining to an appender.
       
   167      *
       
   168      * Parses the following patterns:
       
   169      *
       
   170      * Appender class:
       
   171      * <pre>
       
   172      * log4php.appender.<name> = <class>
       
   173      * </pre>
       
   174      *
       
   175      * Appender parameter:
       
   176      * <pre>
       
   177      * log4php.appender.<name>.<param> = <value>
       
   178      * </pre>
       
   179      *
       
   180      * Appender threshold:
       
   181      * <pre>
       
   182      * log4php.appender.<name>.threshold = <level>
       
   183      * </pre>
       
   184      *
       
   185      * Appender layout:
       
   186      * <pre>
       
   187      * log4php.appender.<name>.layout = <layoutClass>
       
   188      * </pre>
       
   189      *
       
   190      * Layout parameter:
       
   191      * <pre>
       
   192      * log4php.appender.<name>.layout.<param> = <value>
       
   193      * </pre>
       
   194      *
       
   195      * For example, a full appender config might look like:
       
   196      * <pre>
       
   197      * log4php.appender.myAppender = LoggerAppenderConsole
       
   198      * log4php.appender.myAppender.threshold = info
       
   199      * log4php.appender.myAppender.target = stdout
       
   200      * log4php.appender.myAppender.layout = LoggerLayoutPattern
       
   201      * log4php.appender.myAppender.layout.conversionPattern = "%d %c: %m%n"
       
   202      * </pre>
       
   203      *
       
   204      * After parsing all these options, the following configuration can be
       
   205      * found under $this->config['appenders']['myAppender']:
       
   206      * <pre>
       
   207      * array(
       
   208      *    'class' => LoggerAppenderConsole,
       
   209      *    'threshold' => info,
       
   210      *    'params' => array(
       
   211      *        'target' => 'stdout'
       
   212      *    ),
       
   213      *    'layout' => array(
       
   214      *        'class' => 'LoggerAppenderConsole',
       
   215      *        'params' => array(
       
   216      *            'conversionPattern' => '%d %c: %m%n'
       
   217      *        )
       
   218      *    )
       
   219      * )
       
   220      * </pre>
       
   221      *
       
   222      * @param string $key
       
   223      * @param string $value
       
   224      */
       
   225     private function parseAppender($key, $value) {
       
   226 
       
   227         // Remove the appender prefix from key
       
   228         $subKey = substr($key, strlen(self::APPENDER_PREFIX));
       
   229 
       
   230         // Divide the string by dots
       
   231         $parts = explode('.', $subKey);
       
   232         $count = count($parts);
       
   233 
       
   234         // The first part is always the appender name
       
   235         $name = trim($parts[0]);
       
   236 
       
   237         // Only one part - this line defines the appender class
       
   238         if ($count == 1) {
       
   239             $this->config['appenders'][$name]['class'] = $value;
       
   240             return;
       
   241         } // Two parts - either a parameter, a threshold or layout class
       
   242         else if ($count == 2) {
       
   243 
       
   244             if ($parts[1] == 'layout') {
       
   245                 $this->config['appenders'][$name]['layout']['class'] = $value;
       
   246                 return;
       
   247             } else if ($parts[1] == 'threshold') {
       
   248                 $this->config['appenders'][$name]['threshold'] = $value;
       
   249                 return;
       
   250             } else {
       
   251                 $this->config['appenders'][$name]['params'][$parts[1]] = $value;
       
   252                 return;
       
   253             }
       
   254         } // Three parts - this can only be a layout parameter
       
   255         else if ($count == 3) {
       
   256             if ($parts[1] == 'layout') {
       
   257                 $this->config['appenders'][$name]['layout']['params'][$parts[2]] = $value;
       
   258                 return;
       
   259             }
       
   260         }
       
   261 
       
   262         trigger_error("log4php: Don't know how to parse the following line: \"$key = $value\". Skipping.");
       
   263     }
       
   264 
       
   265     /**
       
   266      * Parses a renderer definition.
       
   267      *
       
   268      * Renderers are defined as:
       
   269      * <pre>
       
   270      * log4php.renderer.<renderedClass> = <renderingClass>
       
   271      * </pre>
       
   272      *
       
   273      * @param string $key log4php.renderer.<renderedClass>
       
   274      * @param string $value <renderingClass>
       
   275      */
       
   276     private function parseRenderer($key, $value) {
       
   277         // Remove the appender prefix from key
       
   278         $renderedClass = substr($key, strlen(self::APPENDER_PREFIX));
       
   279         $renderingClass = $value;
       
   280 
       
   281         $this->config['renderers'][] = compact('renderedClass', 'renderingClass');
       
   282     }
       
   283 
       
   284     /** Helper method. Returns true if $str begins with $sub. */
       
   285     private function beginsWith($str, $sub) {
       
   286         return (strncmp($str, $sub, strlen($sub)) == 0);
       
   287     }
       
   288 
       
   289 
       
   290 }
       
   291