The casual user does not have to deal with this class directly.

* *

The structure of the logger hierarchy is maintained by the * getLogger method. The hierarchy is such that children link * to their parent but parents do not have any pointers to their * children. Moreover, loggers can be instantiated in any order, in * particular descendant before ancestor.

* *

In case a descendant is created before a particular ancestor, * then it creates a provision node for the ancestor and adds itself * to the provision node. Other descendants of the same ancestor add * themselves to the previously created provision node.

* * @version $Revision$ * @package log4php */ /* * TODO: * - addHierarchyEventListener($listener) not supported * - emitNoAppenderWarning($cat) not supported * - fireAddAppenderEvent not supported */ class LoggerHierarchy { /** Default Factory */ protected $defaultFactory; /** array hierarchy tree. saves here all loggers */ protected $ht = array(); /** The root Logger */ protected $root = null; /** LoggerRendererMap */ protected $rendererMap; /** LoggerLevel main level threshold */ protected $threshold; /** * Create a new logger hierarchy. * @param object $root the root logger */ public function __construct(LoggerRoot $root) { $this->root = $root; $this->setThreshold(LoggerLevel::getLevelAll()); $this->rendererMap = new LoggerRendererMap(); } /** * This call will clear all logger definitions from the internal hashtable. */ public function clear() { $this->ht = array(); } /** * Check if the named logger exists in the hierarchy. * @param string $name * @return boolean */ public function exists($name) { return isset($this->ht[$name]); } /** * Returns all the currently defined categories in this hierarchy as an array. * @return array */ public function getCurrentLoggers() { return array_values($this->ht); } /** * Return a new logger instance named as the first parameter using the default factory. * * @param string $name logger name * @param LoggerFactory $factory a {@link LoggerFactory} instance or null * @return Logger */ public function getLogger($name) { if(!isset($this->ht[$name])) { $this->ht[$name] = new Logger($name);; // TODO: isn't necessary, access via singleton? // $this->ht[$name]->setHierarchy($this); $nodes = explode('.', $name); $firstNode = array_shift($nodes); // if name is not a first node but another first node is their if($firstNode != $name and isset($this->ht[$firstNode])) { $this->ht[$name]->setParent($this->ht[$firstNode]); } else { // if there is no father, set root logger as father $this->ht[$name]->setParent($this->root); } // if there are more nodes than one if(count($nodes) > 0) { // find parent node foreach($nodes as $node) { $parentNode = "$firstNode.$node"; if(isset($this->ht[$parentNode]) and $parentNode != $name) { $this->ht[$name]->setParent($this->ht[$parentNode]); } $firstNode .= ".$node"; } } } return $this->ht[$name]; } /** * @return LoggerRendererMap Get the renderer map for this hierarchy. */ public function getRendererMap() { return $this->rendererMap; } /** * @return LoggerRoot Get the root of this hierarchy. */ public function getRootLogger() { if(!isset($this->root) or $this->root == null) { $this->root = new LoggerRoot(); } return $this->root; } /** * @return LoggerLevel Returns the threshold Level. */ public function getThreshold() { return $this->threshold; } /** * This method will return true if this repository is disabled * for level object passed as parameter and false otherwise. * @return boolean */ public function isDisabled(LoggerLevel $level) { return ($this->threshold->toInt() > $level->toInt()); } /** * Reset all values contained in this hierarchy instance to their * default. * * This removes all appenders from all categories, sets * the level of all non-root categories to null, * sets their additivity flag to true and sets the level * of the root logger to {@link LOGGER_LEVEL_DEBUG}. Moreover, * message disabling is set its default "off" value. * *

Existing categories are not removed. They are just reset. * *

This method should be used sparingly and with care as it will * block all logging until it is completed.

*/ public function resetConfiguration() { $root = $this->getRootLogger(); $root->setLevel(LoggerLevel::getLevelDebug()); $this->setThreshold(LoggerLevel::getLevelAll()); $this->shutDown(); $loggers = $this->getCurrentLoggers(); $enumLoggers = count($loggers); for($i = 0; $i < $enumLoggers; $i++) { $loggers[$i]->setLevel(null); $loggers[$i]->setAdditivity(true); $loggers[$i]->removeAllAppenders(); } $this->rendererMap->clear(); LoggerAppenderPool::clear(); } /** * set a new threshold level * * @param LoggerLevel $l */ public function setThreshold(LoggerLevel $l) { if($l !== null) { $this->threshold = $l; } } /** * Shutting down a hierarchy will safely close and remove * all appenders in all categories including the root logger. * *

Some appenders such as {@link LoggerSocketAppender} * need to be closed before the * application exists. Otherwise, pending logging events might be * lost. * *

The shutdown method is careful to close nested * appenders before closing regular appenders. This is allows * configurations where a regular appender is attached to a logger * and again to a nested appender. */ public function shutdown() { $this->root->removeAllAppenders(); $cats = $this->getCurrentLoggers(); $enumCats = count($cats); if($enumCats > 0) { for($i = 0; $i < $enumCats; $i++) { $cats[$i]->removeAllAppenders(); } } } }