diff --git a/library/log4php/configurators/LoggerConfigurationAdapterXML.php b/library/log4php/configurators/LoggerConfigurationAdapterXML.php new file mode 100644 --- /dev/null +++ b/library/log4php/configurators/LoggerConfigurationAdapterXML.php @@ -0,0 +1,278 @@ + array(), + 'loggers' => array(), + 'renderers' => array(), + ); + + public function convert($url) { + $xml = $this->loadXML($url); + + $this->parseConfiguration($xml); + + // Parse the node + if (isset($xml->root)) { + $this->parseRootLogger($xml->root); + } + + // Process nodes + foreach ($xml->logger as $logger) { + $this->parseLogger($logger); + } + + // Process nodes + foreach ($xml->appender as $appender) { + $this->parseAppender($appender); + } + + // Process nodes + foreach ($xml->renderer as $rendererNode) { + $this->parseRenderer($rendererNode); + } + + // Process node + foreach ($xml->defaultRenderer as $rendererNode) { + $this->parseDefaultRenderer($rendererNode); + } + + return $this->config; + } + + /** + * Loads and validates the XML. + * @param string $url Input XML. + */ + private function loadXML($url) { + if (!file_exists($url)) { + throw new LoggerException("File [$url] does not exist."); + } + + libxml_clear_errors(); + $oldValue = libxml_use_internal_errors(true); + + // Load XML + $xml = @simplexml_load_file($url); + if ($xml === false) { + + $errorStr = ""; + foreach (libxml_get_errors() as $error) { + $errorStr .= $error->message; + } + + throw new LoggerException("Error loading configuration file: " . trim($errorStr)); + } + + libxml_clear_errors(); + libxml_use_internal_errors($oldValue); + + return $xml; + } + + /** + * Parses the node. + */ + private function parseConfiguration(SimpleXMLElement $xml) { + $attributes = $xml->attributes(); + if (isset($attributes['threshold'])) { + $this->config['threshold'] = (string)$attributes['threshold']; + } + } + + /** Parses an node. */ + private function parseAppender(SimpleXMLElement $node) { + $name = $this->getAttributeValue($node, 'name'); + if (empty($name)) { + $this->warn("An node is missing the required 'name' attribute. Skipping appender definition."); + return; + } + + $appender = array(); + $appender['class'] = $this->getAttributeValue($node, 'class'); + + if (isset($node['threshold'])) { + $appender['threshold'] = $this->getAttributeValue($node, 'threshold'); + } + + if (isset($node->layout)) { + $appender['layout'] = $this->parseLayout($node->layout, $name); + } + + if (count($node->param) > 0) { + $appender['params'] = $this->parseParameters($node); + } + + foreach ($node->filter as $filterNode) { + $appender['filters'][] = $this->parseFilter($filterNode); + } + + $this->config['appenders'][$name] = $appender; + } + + /** Parses a node. */ + private function parseLayout(SimpleXMLElement $node, $appenderName) { + $layout = array(); + $layout['class'] = $this->getAttributeValue($node, 'class'); + + if (count($node->param) > 0) { + $layout['params'] = $this->parseParameters($node); + } + + return $layout; + } + + /** Parses any child nodes returning them in an array. */ + private function parseParameters($paramsNode) { + $params = array(); + + foreach ($paramsNode->param as $paramNode) { + if (empty($paramNode['name'])) { + $this->warn("A node is missing the required 'name' attribute. Skipping parameter."); + continue; + } + + $name = $this->getAttributeValue($paramNode, 'name'); + $value = $this->getAttributeValue($paramNode, 'value'); + + $params[$name] = $value; + } + + return $params; + } + + /** Parses a node. */ + private function parseRootLogger(SimpleXMLElement $node) { + $logger = array(); + + if (isset($node->level)) { + $logger['level'] = $this->getAttributeValue($node->level, 'value'); + } + + $logger['appenders'] = $this->parseAppenderReferences($node); + + $this->config['rootLogger'] = $logger; + } + + /** Parses a node. */ + private function parseLogger(SimpleXMLElement $node) { + $logger = array(); + + $name = $this->getAttributeValue($node, 'name'); + if (empty($name)) { + $this->warn("A node is missing the required 'name' attribute. Skipping logger definition."); + return; + } + + if (isset($node->level)) { + $logger['level'] = $this->getAttributeValue($node->level, 'value'); + } + + if (isset($node['additivity'])) { + $logger['additivity'] = $this->getAttributeValue($node, 'additivity'); + } + + $logger['appenders'] = $this->parseAppenderReferences($node); + + // Check for duplicate loggers + if (isset($this->config['loggers'][$name])) { + $this->warn("Duplicate logger definition [$name]. Overwriting."); + } + + $this->config['loggers'][$name] = $logger; + } + + /** + * Parses a node for appender references and returns them in an array. + * + * Previous versions supported appender-ref, as well as appender_ref so both + * are parsed for backward compatibility. + */ + private function parseAppenderReferences(SimpleXMLElement $node) { + $refs = array(); + foreach ($node->appender_ref as $ref) { + $refs[] = $this->getAttributeValue($ref, 'ref'); + } + + foreach ($node->{'appender-ref'} as $ref) { + $refs[] = $this->getAttributeValue($ref, 'ref'); + } + + return $refs; + } + + /** Parses a node. */ + private function parseFilter($filterNode) { + $filter = array(); + $filter['class'] = $this->getAttributeValue($filterNode, 'class'); + + if (count($filterNode->param) > 0) { + $filter['params'] = $this->parseParameters($filterNode); + } + + return $filter; + } + + /** Parses a node. */ + private function parseRenderer(SimpleXMLElement $node) { + $renderedClass = $this->getAttributeValue($node, 'renderedClass'); + $renderingClass = $this->getAttributeValue($node, 'renderingClass'); + + $this->config['renderers'][] = compact('renderedClass', 'renderingClass'); + } + + /** Parses a node. */ + private function parseDefaultRenderer(SimpleXMLElement $node) { + $renderingClass = $this->getAttributeValue($node, 'renderingClass'); + + // Warn on duplicates + if (isset($this->config['defaultRenderer'])) { + $this->warn("Duplicate node. Overwriting."); + } + + $this->config['defaultRenderer'] = $renderingClass; + } + + // ****************************************** + // ** Helper methods ** + // ****************************************** + + private function getAttributeValue(SimpleXMLElement $node, $name) { + return isset($node[$name]) ? (string)$node[$name] : null; + } + + private function warn($message) { + trigger_error("log4php: " . $message, E_USER_WARNING); + } +} +