1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19:
20:
21: 22: 23: 24: 25: 26: 27: 28: 29:
30: class LoggerConfigurationAdapterXML implements LoggerConfigurationAdapter
31: {
32:
33: const SCHEMA_PATH = '/../xml/log4php.xsd';
34:
35: private $config = array(
36: 'appenders' => array(),
37: 'loggers' => array(),
38: 'renderers' => array(),
39: );
40:
41: public function convert($url) {
42: $xml = $this->loadXML($url);
43:
44: $this->parseConfiguration($xml);
45:
46:
47: if (isset($xml->root)) {
48: $this->parseRootLogger($xml->root);
49: }
50:
51:
52: foreach($xml->logger as $logger) {
53: $this->parseLogger($logger);
54: }
55:
56:
57: foreach($xml->appender as $appender) {
58: $this->parseAppender($appender);
59: }
60:
61:
62: foreach($xml->renderer as $rendererNode) {
63: $this->parseRenderer($rendererNode);
64: }
65:
66:
67: foreach($xml->defaultRenderer as $rendererNode) {
68: $this->parseDefaultRenderer($rendererNode);
69: }
70:
71: return $this->config;
72: }
73:
74: 75: 76: 77:
78: private function loadXML($url) {
79: if (!file_exists($url)) {
80: throw new LoggerException("File [$url] does not exist.");
81: }
82:
83: libxml_clear_errors();
84: $oldValue = libxml_use_internal_errors(true);
85:
86:
87: $xml = @simplexml_load_file($url);
88: if ($xml === false) {
89:
90: $errorStr = "";
91: foreach(libxml_get_errors() as $error) {
92: $errorStr .= $error->message;
93: }
94:
95: throw new LoggerException("Error loading configuration file: " . trim($errorStr));
96: }
97:
98: libxml_clear_errors();
99: libxml_use_internal_errors($oldValue);
100:
101: return $xml;
102: }
103:
104: 105: 106:
107: private function parseConfiguration(SimpleXMLElement $xml) {
108: $attributes = $xml->attributes();
109: if (isset($attributes['threshold'])) {
110: $this->config['threshold'] = (string) $attributes['threshold'];
111: }
112: }
113:
114:
115: private function parseAppender(SimpleXMLElement $node) {
116: $name = $this->getAttributeValue($node, 'name');
117: if (empty($name)) {
118: $this->warn("An <appender> node is missing the required 'name' attribute. Skipping appender definition.");
119: return;
120: }
121:
122: $appender = array();
123: $appender['class'] = $this->getAttributeValue($node, 'class');
124:
125: if (isset($node['threshold'])) {
126: $appender['threshold'] = $this->getAttributeValue($node, 'threshold');
127: }
128:
129: if (isset($node->layout)) {
130: $appender['layout']= $this->parseLayout($node->layout, $name);
131: }
132:
133: if (count($node->param) > 0) {
134: $appender['params'] = $this->parseParameters($node);
135: }
136:
137: foreach($node->filter as $filterNode) {
138: $appender['filters'][] = $this->parseFilter($filterNode);
139: }
140:
141: $this->config['appenders'][$name] = $appender;
142: }
143:
144:
145: private function parseLayout(SimpleXMLElement $node, $appenderName) {
146: $layout = array();
147: $layout['class'] = $this->getAttributeValue($node, 'class');
148:
149: if (count($node->param) > 0) {
150: $layout['params'] = $this->parseParameters($node);
151: }
152:
153: return $layout;
154: }
155:
156:
157: private function parseParameters($paramsNode) {
158: $params = array();
159:
160: foreach($paramsNode->param as $paramNode) {
161: if (empty($paramNode['name'])) {
162: $this->warn("A <param> node is missing the required 'name' attribute. Skipping parameter.");
163: continue;
164: }
165:
166: $name = $this->getAttributeValue($paramNode, 'name');
167: $value = $this->getAttributeValue($paramNode, 'value');
168:
169: $params[$name] = $value;
170: }
171:
172: return $params;
173: }
174:
175:
176: private function parseRootLogger(SimpleXMLElement $node) {
177: $logger = array();
178:
179: if (isset($node->level)) {
180: $logger['level'] = $this->getAttributeValue($node->level, 'value');
181: }
182:
183: $logger['appenders'] = $this->parseAppenderReferences($node);
184:
185: $this->config['rootLogger'] = $logger;
186: }
187:
188:
189: private function parseLogger(SimpleXMLElement $node) {
190: $logger = array();
191:
192: $name = $this->getAttributeValue($node, 'name');
193: if (empty($name)) {
194: $this->warn("A <logger> node is missing the required 'name' attribute. Skipping logger definition.");
195: return;
196: }
197:
198: if (isset($node->level)) {
199: $logger['level'] = $this->getAttributeValue($node->level, 'value');
200: }
201:
202: if (isset($node['additivity'])) {
203: $logger['additivity'] = $this->getAttributeValue($node, 'additivity');
204: }
205:
206: $logger['appenders'] = $this->parseAppenderReferences($node);
207:
208:
209: if (isset($this->config['loggers'][$name])) {
210: $this->warn("Duplicate logger definition [$name]. Overwriting.");
211: }
212:
213: $this->config['loggers'][$name] = $logger;
214: }
215:
216: 217: 218: 219: 220: 221:
222: private function parseAppenderReferences(SimpleXMLElement $node) {
223: $refs = array();
224: foreach($node->appender_ref as $ref) {
225: $refs[] = $this->getAttributeValue($ref, 'ref');
226: }
227:
228: foreach($node->{'appender-ref'} as $ref) {
229: $refs[] = $this->getAttributeValue($ref, 'ref');
230: }
231:
232: return $refs;
233: }
234:
235:
236: private function parseFilter($filterNode) {
237: $filter = array();
238: $filter['class'] = $this->getAttributeValue($filterNode, 'class');
239:
240: if (count($filterNode->param) > 0) {
241: $filter['params'] = $this->parseParameters($filterNode);
242: }
243:
244: return $filter;
245: }
246:
247:
248: private function parseRenderer(SimpleXMLElement $node) {
249: $renderedClass = $this->getAttributeValue($node, 'renderedClass');
250: $renderingClass = $this->getAttributeValue($node, 'renderingClass');
251:
252: $this->config['renderers'][] = compact('renderedClass', 'renderingClass');
253: }
254:
255:
256: private function parseDefaultRenderer(SimpleXMLElement $node) {
257: $renderingClass = $this->getAttributeValue($node, 'renderingClass');
258:
259:
260: if(isset($this->config['defaultRenderer'])) {
261: $this->warn("Duplicate <defaultRenderer> node. Overwriting.");
262: }
263:
264: $this->config['defaultRenderer'] = $renderingClass;
265: }
266:
267:
268:
269:
270:
271: private function getAttributeValue(SimpleXMLElement $node, $name) {
272: return isset($node[$name]) ? (string) $node[$name] : null;
273: }
274:
275: private function warn($message) {
276: trigger_error("log4php: " . $message, E_USER_WARNING);
277: }
278: }
279:
280: