OSDN Git Service

初回コミット(v2.6.17.1)
[magic3/magic3.git] / include / lib / log4php / xml / LoggerDOMConfigurator.php
1 <?php
2 /**
3  * log4php is a PHP port of the log4j java logging package.
4  * 
5  * <p>This framework is based on log4j (see {@link http://jakarta.apache.org/log4j log4j} for details).</p>
6  * <p>Design, strategies and part of the methods documentation are developed by log4j team 
7  * (Ceki Gülcü as log4j project founder and 
8  * {@link http://jakarta.apache.org/log4j/docs/contributors.html contributors}).</p>
9  *
10  * <p>PHP port, extensions and modifications by VxR. All rights reserved.<br>
11  * For more information, please see {@link http://www.vxr.it/log4php/}.</p>
12  *
13  * <p>This software is published under the terms of the LGPL License
14  * a copy of which has been included with this distribution in the LICENSE file.</p>
15  * 
16  * @package log4php
17  * @subpackage xml
18  */
19
20 /**
21  * @ignore 
22  */
23 if (!defined('LOG4PHP_DIR')) define('LOG4PHP_DIR', dirname(__FILE__) . '/..');
24  
25 require_once(LOG4PHP_DIR . '/helpers/LoggerOptionConverter.php');
26 require_once(LOG4PHP_DIR . '/or/LoggerObjectRenderer.php');
27 require_once(LOG4PHP_DIR . '/spi/LoggerConfigurator.php');
28 require_once(LOG4PHP_DIR . '/LoggerAppender.php');
29 require_once(LOG4PHP_DIR . '/LoggerLayout.php');
30 require_once(LOG4PHP_DIR . '/LoggerLog.php');
31 require_once(LOG4PHP_DIR . '/LoggerManager.php');
32
33 define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_APPENDER_STATE',    1000);
34 define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_LAYOUT_STATE',      1010);
35 define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_ROOT_STATE',        1020);
36 define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_LOGGER_STATE',      1030);
37 define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_FILTER_STATE',      1040);
38
39 define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_DEFAULT_FILENAME',  './log4php.xml');
40
41 /**
42  * @var string the default configuration document
43  */
44 define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_DEFAULT_CONFIGURATION', 
45 '<?xml version="1.0" ?>
46 <log4php:configuration threshold="all">
47     <appender name="A1" class="LoggerAppenderEcho">
48         <layout class="LoggerLayoutSimple" />
49     </appender>
50     <root>
51         <level value="debug" />
52         <appender_ref ref="A1" />
53     </root>
54 </log4php:configuration>');
55
56 /**
57  * @var string the elements namespace
58  */
59 define('LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS', 'HTTP://WWW.VXR.IT/LOG4PHP/'); 
60
61 /**
62  * Use this class to initialize the log4php environment using expat parser.
63  *
64  * <p>Read the log4php.dtd included in the documentation directory. Note that
65  * php parser does not validate the document.</p>
66  *
67  * <p>Sometimes it is useful to see how log4php is reading configuration
68  * files. You can enable log4php internal logging by setting the <var>debug</var> 
69  * attribute in the <var>log4php:configuration</var> element. As in
70  * <pre>
71  * &lt;log4php:configuration <b>debug="true"</b> xmlns:log4php="http://www.vxr.it/log4php/">
72  * ...
73  * &lt;/log4php:configuration>
74  * </pre>
75  *
76  * <p>There are sample XML files included in the package under <b>tests/</b> 
77  * subdirectories.</p>
78  *
79  * @author VxR <vxr@vxr.it>
80  * @version $Revision: 2 $
81  * @package log4php
82  * @subpackage xml
83  * @since 0.4 
84  */
85 class LoggerDOMConfigurator extends LoggerConfigurator {
86
87     /**
88      * @var LoggerHierarchy
89      */
90     var $repository;
91     
92     /**
93      * @var array state stack 
94      */
95     var $state;
96
97     /**
98      * @var Logger parsed Logger  
99      */
100     var $logger;
101     
102     /**
103      * @var LoggerAppender parsed LoggerAppender 
104      */
105     var $appender;
106     
107     /**
108      * @var LoggerFilter parsed LoggerFilter 
109      */
110     var $filter;
111     
112     /**
113      * @var LoggerLayout parsed LoggerLayout 
114      */
115     var $layout;
116     
117     /**
118      * Constructor
119      */
120     function LoggerDOMConfigurator()
121     {
122         $this->state    = array();
123         $this->logger   = null;
124         $this->appender = null;
125         $this->filter   = null;
126         $this->layout   = null;
127     }
128     
129     /**
130      * Configure the default repository using the resource pointed by <b>url</b>.
131      * <b>Url</b> is any valid resurce as defined in {@link PHP_MANUAL#file} function.
132      * Note that the resource will be search with <i>use_include_path</i> parameter 
133      * set to "1".
134      *
135      * @param string $url
136      * @static
137      */
138     function configure($url = '')
139     {
140         $configurator = new LoggerDOMConfigurator();
141         $repository =& LoggerManager::getLoggerRepository();
142         return $configurator->doConfigure($url, $repository);
143     }
144     
145     /**
146      * Configure the given <b>repository</b> using the resource pointed by <b>url</b>.
147      * <b>Url</b> is any valid resurce as defined in {@link PHP_MANUAL#file} function.
148      * Note that the resource will be search with <i>use_include_path</i> parameter 
149      * set to "1".
150      *
151      * @param string $url
152      * @param LoggerHierarchy &$repository
153      */
154     function doConfigure($url = '', &$repository)
155     {
156         $xmlData = '';
157         if (!empty($url))
158             $xmlData = implode('', file($url, 1));
159         return $this->doConfigureByString($xmlData, $repository);
160     }
161     
162     /**
163      * Configure the given <b>repository</b> using the configuration written in <b>xmlData</b>.
164      * Do not call this method directly. Use {@link doConfigure()} instead.
165      * @param string $xmlData
166      * @param LoggerHierarchy &$repository
167      */
168     function doConfigureByString($xmlData, &$repository)
169     {
170         return $this->parse($xmlData, $repository);
171     }
172     
173     /**
174      * @param LoggerHierarchy &$repository
175      */
176     function doConfigureDefault(&$repository)
177     {
178         return $this->doConfigureByString(LOG4PHP_LOGGER_DOM_CONFIGURATOR_DEFAULT_CONFIGURATION, $repository);
179     }
180     
181     /**
182      * @param string $xmlData
183      */
184     function parse($xmlData, &$repository)
185     {
186         // LoggerManager::resetConfiguration();
187         $this->repository =& $repository;
188
189         $parser = xml_parser_create_ns();
190     
191         xml_set_object($parser, &$this);
192         xml_set_element_handler($parser, "tagOpen", "tagClose");
193         
194         $result = xml_parse($parser, $xmlData, true);
195         if (!$result) {
196             $errorCode = xml_get_error_code($parser);
197             $errorStr = xml_error_string($errorCode);
198             $errorLine = xml_get_current_line_number($parser);
199             LoggerLog::warn(
200                 "LoggerDOMConfigurator::parse() ".
201                 "Parsing error [{$errorCode}] {$errorStr}, line {$errorLine}"
202             );
203             $this->repository->resetConfiguration();
204         } else {
205             xml_parser_free($parser);
206         }
207         return $result;
208     }
209     
210     /**
211      * @param mixed $parser
212      * @param string $tag
213      * @param array $attribs
214      *
215      * @todo In 'LOGGER' case find a better way to detect 'getLogger()' method
216      */
217     function tagOpen($parser, $tag, $attribs)
218     {
219         switch ($tag) {
220         
221             case 'CONFIGURATION' :
222             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':CONFIGURATION':
223             
224                 LoggerLog::debug("LoggerDOMConfigurator::tagOpen() CONFIGURATION");
225
226                 if (isset($attribs['THRESHOLD'])) {
227                 
228                     $this->repository->setThreshold(
229                         LoggerOptionConverter::toLevel(
230                             $this->subst($attribs['THRESHOLD']), 
231                             $this->repository->getThreshold()
232                         )
233                     );
234                 }
235                 if (isset($attribs['DEBUG'])) {
236                     $debug = LoggerOptionConverter::toBoolean($this->subst($attribs['DEBUG']), LoggerLog::internalDebugging());
237                     $this->repository->debug = $debug;
238                     LoggerLog::internalDebugging($debug);
239                     LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LOG4PHP:CONFIGURATION. Internal Debug turned ".($debug ? 'on':'off'));
240                     
241                 }
242                 break;
243                 
244             case 'APPENDER' :
245             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':APPENDER':
246             
247                 unset($this->appender);
248                 $this->appender = null;
249                 
250                 $name  = $this->subst(@$attribs['NAME']);
251                 $class = $this->subst(@$attribs['CLASS']);
252                 
253                 LoggerLog::debug("LoggerDOMConfigurator::tagOpen():tag=[$tag]:name=[$name]:class=[$class]");
254                 
255                 $this->appender =& LoggerAppender::singleton($name, $class);
256                 if ($this->appender === null) {
257                     LoggerLog::warn("LoggerDOMConfigurator::tagOpen() APPENDER cannot instantiate appender '$name'");
258                 }
259                 $this->state[] = LOG4PHP_LOGGER_DOM_CONFIGURATOR_APPENDER_STATE;
260                 break;
261                 
262             case 'APPENDER_REF' :
263             case 'APPENDER-REF' :
264             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':APPENDER_REF':
265             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':APPENDER-REF':
266             
267             
268                 if (isset($attribs['REF']) and !empty($attribs['REF'])) {
269                     $appenderName = $this->subst($attribs['REF']);
270                     
271                     LoggerLog::debug("LoggerDOMConfigurator::tagOpen() APPENDER-REF ref='$appenderName'");        
272                     
273                     $appender =& LoggerAppender::singleton($appenderName);
274                     if ($appender !== null) {
275                         switch (end($this->state)) {
276                             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_LOGGER_STATE:
277                             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_ROOT_STATE:                
278                                 $this->logger->addAppender($appender);
279                                 break;
280                         }
281                     } else {
282                         LoggerLog::warn("LoggerDOMConfigurator::tagOpen() APPENDER-REF ref '$appenderName' points to a null appender");
283                     }
284                 } else {
285                     LoggerLog::warn("LoggerDOMConfigurator::tagOpen() APPENDER-REF ref not set or empty");            
286                 }
287                 break;
288                 
289             case 'FILTER' :
290             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':FILTER':
291             
292                 LoggerLog::debug("LoggerDOMConfigurator::tagOpen() FILTER");
293                             
294                 unset($this->filter);
295                 $this->filter = null;
296
297                 $filterName = basename($this->subst(@$attribs['CLASS']));
298                 if (!empty($filterName)) {
299                     if (!class_exists($filterName)) {
300                         @include_once(LOG4PHP_DIR . "/varia/{$filterName}.php");
301                     }
302                     if (class_exists($filterName)) {
303                         $this->filter = new $filterName();
304                     } else {
305                         LoggerLog::warn("LoggerDOMConfigurator::tagOpen() FILTER. class '$filterName' doesnt exist");
306                     }
307                     $this->state[] = LOG4PHP_LOGGER_DOM_CONFIGURATOR_FILTER_STATE;
308                 } else {
309                     LoggerLog::warn("LoggerDOMConfigurator::tagOpen() FILTER filter name cannot be empty");
310                 }
311                 break;
312                 
313             case 'LAYOUT':
314             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':LAYOUT':
315             
316                 $class = @$attribs['CLASS'];
317
318                 LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LAYOUT class='{$class}'");
319
320                 $this->layout = LoggerLayout::factory($this->subst($class));
321                 if ($this->layout === null)
322                     LoggerLog::warn("LoggerDOMConfigurator::tagOpen() LAYOUT unable to instanciate class='{$class}'");
323                 
324                 $this->state[] = LOG4PHP_LOGGER_DOM_CONFIGURATOR_LAYOUT_STATE;
325                 break;
326             
327             case 'LOGGER':
328             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':LOGGER':
329             
330                 // $this->logger is assigned by reference.
331                 // Only '$this->logger=null;' destroys referenced object
332                 unset($this->logger);
333                 $this->logger = null;
334                 
335                 $loggerName = $this->subst(@$attribs['NAME']);
336                 if (!empty($loggerName)) {
337                     LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LOGGER. name='$loggerName'");        
338                     
339                     $class = $this->subst(@$attribs['CLASS']);
340                     if (empty($class)) {
341                         $this->logger =& $this->repository->getLogger($loggerName);
342                     } else {
343                         $className = basename($class);
344                         if (!class_exists($className))  
345                             @include_once("{$class}.php");
346                         if (!class_exists($className)) {
347                             LoggerLog::warn(
348                                 "LoggerDOMConfigurator::tagOpen() LOGGER. ".
349                                 "cannot find '$className'."
350                             );                        
351                         } else {
352                         
353                             if (in_array('getlogger', get_class_methods($className))) {
354                                 $this->logger =& call_user_func(array($className, 'getlogger'), $loggerName);
355                             } else {
356                                 LoggerLog::warn(
357                                     "LoggerDOMConfigurator::tagOpen() LOGGER. ".
358                                     "class '$className' doesnt implement 'getLogger()' method."
359                                 );                        
360                             }
361                         }
362                     }    
363                     if ($this->logger !== null and isset($attribs['ADDITIVITY'])) {
364                         $additivity = LoggerOptionConverter::toBoolean($this->subst($attribs['ADDITIVITY']), true);     
365                         $this->logger->setAdditivity($additivity);
366                     }
367                 } else {
368                     LoggerLog::warn("LoggerDOMConfigurator::tagOpen() LOGGER. Attribute 'name' is not set or is empty.");
369                 }
370                 $this->state[] = LOG4PHP_LOGGER_DOM_CONFIGURATOR_LOGGER_STATE;;
371                 break;
372             
373             case 'LEVEL':
374             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':LEVEL':
375             case 'PRIORITY':
376             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':PRIORITY':
377             
378                 if (!isset($attribs['VALUE'])) {
379                     LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LEVEL value not set");
380                     break;
381                 }
382                     
383                 LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LEVEL value={$attribs['VALUE']}");
384                 
385                 if ($this->logger === null) { 
386                     LoggerLog::warn("LoggerDOMConfigurator::tagOpen() LEVEL. parent logger is null");
387                     break;
388                 }
389         
390                 switch (end($this->state)) {
391                     case LOG4PHP_LOGGER_DOM_CONFIGURATOR_ROOT_STATE:
392                         $this->logger->setLevel(
393                             LoggerOptionConverter::toLevel(
394                                 $this->subst($attribs['VALUE']), 
395                                 $this->logger->getLevel()
396                             )
397                         );
398                         LoggerLog::debug("LoggerDOMConfigurator::tagOpen() LEVEL root level is now '{$attribs['VALUE']}' ");                
399                         break;
400                     case LOG4PHP_LOGGER_DOM_CONFIGURATOR_LOGGER_STATE:
401                         $this->logger->setLevel(
402                             LoggerOptionConverter::toLevel(
403                                 $this->subst($attribs['VALUE']), 
404                                 $this->logger->getLevel()
405                             )
406                         );
407                         break;
408                     default:
409                         LoggerLog::warn("LoggerDOMConfigurator::tagOpen() LEVEL state '{$this->state}' not allowed here");
410                 }
411                 break;
412             
413             case 'PARAM':
414             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':PARAM':
415
416                 LoggerLog::debug("LoggerDOMConfigurator::tagOpen() PARAM");
417                 
418                 if (!isset($attribs['NAME'])) {
419                     LoggerLog::warn(
420                         "LoggerDOMConfigurator::tagOpen() PARAM. ".
421                         "attribute 'name' not defined."
422                     );
423                     break;
424                 }
425                 if (!isset($attribs['VALUE'])) {
426                     LoggerLog::warn(
427                         "LoggerDOMConfigurator::tagOpen() PARAM. ".
428                         "attribute 'value' not defined."
429                     );
430                     break;
431                 }
432                     
433                 switch (end($this->state)) {
434                     case LOG4PHP_LOGGER_DOM_CONFIGURATOR_APPENDER_STATE:
435                         if ($this->appender !== null) {
436                             $this->setter($this->appender, $this->subst($attribs['NAME']), $this->subst($attribs['VALUE']));
437                         } else {
438                             LoggerLog::warn(
439                                 "LoggerDOMConfigurator::tagOpen() PARAM. ".
440                                 " trying to set property to a null appender."
441                             );
442                         }
443                         break;
444                     case LOG4PHP_LOGGER_DOM_CONFIGURATOR_LAYOUT_STATE:
445                         if ($this->layout !== null) {
446                             $this->setter($this->layout, $this->subst($attribs['NAME']), $this->subst($attribs['VALUE']));                
447                         } else {
448                             LoggerLog::warn(
449                                 "LoggerDOMConfigurator::tagOpen() PARAM. ".
450                                 " trying to set property to a null layout."
451                             );
452                         }
453                         break;
454                     case LOG4PHP_LOGGER_DOM_CONFIGURATOR_FILTER_STATE:
455                         if ($this->filter !== null) {
456                             $this->setter($this->filter, $this->subst($attribs['NAME']), $this->subst($attribs['VALUE']));
457                         } else {
458                             LoggerLog::warn(
459                                 "LoggerDOMConfigurator::tagOpen() PARAM. ".
460                                 " trying to set property to a null filter."
461                             );
462                         }
463                         break;
464                     default:
465                         LoggerLog::warn("LoggerDOMConfigurator::tagOpen() PARAM state '{$this->state}' not allowed here");
466                 }
467                 break;
468             
469             case 'RENDERER':
470             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':RENDERER':
471
472                 $renderedClass   = $this->subst(@$attribs['RENDEREDCLASS']);
473                 $renderingClass  = $this->subst(@$attribs['RENDERINGCLASS']);
474         
475                 LoggerLog::debug("LoggerDOMConfigurator::tagOpen() RENDERER renderedClass='$renderedClass' renderingClass='$renderingClass'");
476         
477                 if (!empty($renderedClass) and !empty($renderingClass)) {
478                     $renderer = LoggerObjectRenderer::factory($renderingClass);
479                     if ($renderer === null) {
480                         LoggerLog::warn("LoggerDOMConfigurator::tagOpen() RENDERER cannot instantiate '$renderingClass'");
481                     } else { 
482                         $this->repository->setRenderer($renderedClass, $renderer);
483                     }
484                 } else {
485                     LoggerLog::warn("LoggerDOMConfigurator::tagOpen() RENDERER renderedClass or renderingClass is empty");        
486                 }
487                 break;
488             
489             case 'ROOT':
490             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':ROOT':
491             
492                 LoggerLog::debug("LoggerDOMConfigurator::tagOpen() ROOT");
493                 
494                 $this->logger =& LoggerManager::getRootLogger();
495                 
496                 $this->state[] = LOG4PHP_LOGGER_DOM_CONFIGURATOR_ROOT_STATE;
497                 break;
498                 
499         }
500          
501     }
502
503
504     /**
505      * @param mixed $parser
506      * @param string $tag
507      */
508     function tagClose($parser, $tag)
509     {
510         switch ($tag) {
511         
512             case 'CONFIGURATION' : 
513             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':CONFIGURATION':
514           
515                 LoggerLog::debug("LoggerDOMConfigurator::tagClose() CONFIGURATION");
516                 break;
517                 
518             case 'APPENDER' :
519             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':APPENDER':
520             
521                 LoggerLog::debug("LoggerDOMConfigurator::tagClose() APPENDER");
522                 
523                 if ($this->appender !== null) {
524                     if ($this->appender->requiresLayout() and $this->appender->layout === null) {
525                         $appenderName = $this->appender->getName();
526                         LoggerLog::warn(
527                             "LoggerDOMConfigurator::tagClose() APPENDER. ".
528                             "'$appenderName' requires a layout that is not defined. ".
529                             "Using a simple layout"
530                         );
531                         $this->appender->setLayout(LoggerLayout::factory('LoggerLayoutSimple'));
532                     }                    
533                     $this->appender->activateOptions();
534                 }        
535                 array_pop($this->state);        
536                 break;
537                 
538             case 'FILTER' :
539             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':FILTER':
540             
541                 LoggerLog::debug("LoggerDOMConfigurator::tagClose() FILTER");
542                             
543                 if ($this->filter !== null) {
544                     $this->filter->activateOptions();
545                     $this->appender->addFilter($this->filter);
546                     $this->filter = null;
547                 }
548                 array_pop($this->state);        
549                 break;
550                 
551             case 'LAYOUT':
552             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':LAYOUT':
553
554                 LoggerLog::debug("LoggerDOMConfigurator::tagClose() LAYOUT");
555
556                 if ($this->appender !== null and $this->layout !== null and $this->appender->requiresLayout()) {
557                     $this->layout->activateOptions();
558                     $this->appender->setLayout($this->layout);
559                     $this->layout = null;
560                 }
561                 array_pop($this->state);
562                 break;
563             
564             case 'LOGGER':
565             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':LOGGER':
566             
567                 LoggerLog::debug("LoggerDOMConfigurator::tagClose() LOGGER");        
568
569                 array_pop($this->state);
570                 break;
571             
572             case 'ROOT':
573             case LOG4PHP_LOGGER_DOM_CONFIGURATOR_XMLNS.':ROOT':
574             
575                 LoggerLog::debug("LoggerDOMConfigurator::tagClose() ROOT");
576
577                 array_pop($this->state);
578                 break;
579         }
580     }
581     
582     /**
583      * @param object $object
584      * @param string $name
585      * @param mixed $value
586      */
587     function setter(&$object, $name, $value)
588     {
589         if (empty($name)) {
590             LoggerLog::debug("LoggerDOMConfigurator::setter() 'name' param cannot be empty");        
591             return false;
592         }
593         $methodName = 'set'.ucfirst($name);
594         if (method_exists($object, $methodName)) {
595             LoggerLog::debug("LoggerDOMConfigurator::setter() Calling ".get_class($object)."::{$methodName}({$value})");
596             return call_user_func(array(&$object, $methodName), $value);
597         } else {
598             LoggerLog::warn("LoggerDOMConfigurator::setter() ".get_class($object)."::{$methodName}() does not exists");
599             return false;
600         }
601     }
602     
603     function subst($value)
604     {
605         return LoggerOptionConverter::substVars($value);
606     }
607
608 }
609 ?>