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 : * The output of the LoggerXmlLayout consists of a series of log4php:event elements.
23 : *
24 : * Configurable parameters:
25 : * - {@link $locationInfo} - If set to true then the file name and line number
26 : * of the origin of the log statement will be included in output.
27 : * - {@link $log4jNamespace} - If set to true then log4j namespace will be used
28 : * instead of log4php namespace. This can be usefull when using log viewers
29 : * which can only parse the log4j namespace such as Apache Chainsaw.
30 : *
31 : * <p>It does not output a complete well-formed XML file.
32 : * The output is designed to be included as an external entity in a separate file to form
33 : * a correct XML file.</p>
34 : *
35 : * Example:
36 : *
37 : * {@example ../../examples/php/layout_xml.php 19}<br>
38 : *
39 : * {@example ../../examples/resources/layout_xml.properties 18}<br>
40 : *
41 : * The above would print:
42 : *
43 : * <pre>
44 : * <log4php:eventSet xmlns:log4php="http://logging.apache.org/log4php/" version="0.3" includesLocationInfo="true">
45 : * <log4php:event logger="root" level="INFO" thread="13802" timestamp="1252456226491">
46 : * <log4php:message><![CDATA[Hello World!]]></log4php:message>
47 : * <log4php:locationInfo class="main" file="examples/php/layout_xml.php" line="6" method="main" />
48 : * </log4php:event>
49 : * </log4php:eventSet>
50 : * </pre>
51 : *
52 : * @version $Revision: 1213283 $
53 : * @package log4php
54 : * @subpackage layouts
55 : */
56 : class LoggerLayoutXml extends LoggerLayout {
57 : const LOG4J_NS_PREFIX ='log4j';
58 : const LOG4J_NS = 'http://jakarta.apache.org/log4j/';
59 :
60 : const LOG4PHP_NS_PREFIX = 'log4php';
61 : const LOG4PHP_NS = 'http://logging.apache.org/log4php/';
62 :
63 : const CDATA_START = '<![CDATA[';
64 : const CDATA_END = ']]>';
65 : const CDATA_PSEUDO_END = ']]>';
66 : const CDATA_EMBEDDED_END = ']]>]]><![CDATA[';
67 :
68 : /**
69 : * If set to true then the file name and line number of the origin of the
70 : * log statement will be output.
71 : * @var boolean
72 : */
73 : protected $locationInfo = true;
74 :
75 : /**
76 : * If set to true, log4j namespace will be used instead of the log4php
77 : * namespace.
78 : * @var boolean
79 : */
80 : protected $log4jNamespace = false;
81 :
82 : /** The namespace in use. */
83 : protected $namespace = self::LOG4PHP_NS;
84 :
85 : /** The namespace prefix in use */
86 : protected $namespacePrefix = self::LOG4PHP_NS_PREFIX;
87 :
88 : public function activateOptions() {
89 5 : if ($this->getLog4jNamespace()) {
90 1 : $this->namespace = self::LOG4J_NS;
91 1 : $this->namespacePrefix = self::LOG4J_NS_PREFIX;
92 1 : } else {
93 4 : $this->namespace = self::LOG4PHP_NS;
94 4 : $this->namespacePrefix = self::LOG4PHP_NS_PREFIX;
95 : }
96 5 : }
97 :
98 : /**
99 : * @return string
100 : */
101 : public function getHeader() {
102 0 : return "<{$this->namespacePrefix}:eventSet ".
103 0 : "xmlns:{$this->namespacePrefix}=\"{$this->namespace}\" ".
104 0 : "version=\"0.3\" ".
105 0 : "includesLocationInfo=\"".($this->getLocationInfo() ? "true" : "false")."\"".
106 0 : ">" . PHP_EOL;
107 : }
108 :
109 : /**
110 : * Formats a {@link LoggerLoggingEvent} in conformance with the log4php.dtd.
111 : *
112 : * @param LoggerLoggingEvent $event
113 : * @return string
114 : */
115 : public function format(LoggerLoggingEvent $event) {
116 5 : $ns = $this->namespacePrefix;
117 :
118 5 : $loggerName = $event->getLoggerName();
119 5 : $timeStamp = number_format((float)($event->getTimeStamp() * 1000), 0, '', '');
120 5 : $thread = $event->getThreadName();
121 5 : $level = $event->getLevel()->toString();
122 :
123 5 : $buf = "<$ns:event logger=\"{$loggerName}\" level=\"{$level}\" thread=\"{$thread}\" timestamp=\"{$timeStamp}\">".PHP_EOL;
124 5 : $buf .= "<$ns:message>";
125 5 : $buf .= $this->encodeCDATA($event->getRenderedMessage());
126 5 : $buf .= "</$ns:message>".PHP_EOL;
127 :
128 5 : $ndc = $event->getNDC();
129 5 : if(!empty($ndc)) {
130 1 : $buf .= "<$ns:NDC><![CDATA[";
131 1 : $buf .= $this->encodeCDATA($ndc);
132 1 : $buf .= "]]></$ns:NDC>".PHP_EOL;
133 1 : }
134 :
135 5 : $mdcMap = $event->getMDCMap();
136 5 : if (!empty($mdcMap)) {
137 1 : $buf .= "<$ns:properties>".PHP_EOL;
138 1 : foreach ($mdcMap as $name=>$value) {
139 1 : $buf .= "<$ns:data name=\"$name\" value=\"$value\" />".PHP_EOL;
140 1 : }
141 1 : $buf .= "</$ns:properties>".PHP_EOL;
142 1 : }
143 :
144 5 : if ($this->getLocationInfo()) {
145 5 : $locationInfo = $event->getLocationInformation();
146 5 : $buf .= "<$ns:locationInfo ".
147 5 : "class=\"" . $locationInfo->getClassName() . "\" ".
148 5 : "file=\"" . htmlentities($locationInfo->getFileName(), ENT_QUOTES) . "\" ".
149 5 : "line=\"" . $locationInfo->getLineNumber() . "\" ".
150 5 : "method=\"" . $locationInfo->getMethodName() . "\" ";
151 5 : $buf .= "/>".PHP_EOL;
152 5 : }
153 :
154 5 : $buf .= "</$ns:event>".PHP_EOL;
155 :
156 5 : return $buf;
157 : }
158 :
159 : /**
160 : * @return string
161 : */
162 : public function getFooter() {
163 0 : return "</{$this->namespacePrefix}:eventSet>" . PHP_EOL;
164 : }
165 :
166 :
167 : /**
168 : * Whether or not file name and line number will be included in the output.
169 : * @return boolean
170 : */
171 : public function getLocationInfo() {
172 5 : return $this->locationInfo;
173 : }
174 :
175 : /**
176 : * The {@link $locationInfo} option takes a boolean value. By default,
177 : * it is set to false which means there will be no location
178 : * information output by this layout. If the the option is set to
179 : * true, then the file name and line number of the statement at the
180 : * origin of the log statement will be output.
181 : */
182 : public function setLocationInfo($flag) {
183 0 : $this->setBoolean('locationInfo', $flag);
184 0 : }
185 :
186 : /**
187 : * @return boolean
188 : */
189 : public function getLog4jNamespace() {
190 5 : return $this->log4jNamespace;
191 : }
192 :
193 : /**
194 : * @param boolean
195 : */
196 : public function setLog4jNamespace($flag) {
197 1 : $this->setBoolean('log4jNamespace', $flag);
198 1 : }
199 :
200 : /**
201 : * Encases a string in CDATA tags, and escapes any existing CDATA end
202 : * tags already present in the string.
203 : * @param string $string
204 : */
205 : private function encodeCDATA($string) {
206 5 : $string = str_replace(self::CDATA_END, self::CDATA_EMBEDDED_END, $string);
207 5 : return self::CDATA_START . $string . self::CDATA_END;
208 : }
209 : }
210 :
|