1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.xml;
19
20 import org.apache.log4j.Layout;
21 import org.apache.log4j.LayoutTest;
22 import org.apache.log4j.Level;
23 import org.apache.log4j.Logger;
24 import org.apache.log4j.NDC;
25 import org.apache.log4j.MDC;
26 import org.apache.log4j.PropertyConfigurator;
27 import org.apache.log4j.util.Transformer;
28 import org.apache.log4j.util.Filter;
29 import org.apache.log4j.util.LineNumberFilter;
30 import org.apache.log4j.util.JunitTestRunnerFilter;
31 import org.apache.log4j.util.XMLTimestampFilter;
32 import org.apache.log4j.util.Compare;
33 import org.apache.log4j.util.XMLDateFilter;
34 import org.apache.log4j.helpers.MDCKeySetExtractor;
35 import org.apache.log4j.spi.LoggingEvent;
36
37 import org.w3c.dom.Document;
38 import org.w3c.dom.Element;
39 import org.w3c.dom.Node;
40 import org.w3c.dom.NodeList;
41
42 import org.xml.sax.InputSource;
43
44 import java.io.Reader;
45 import java.io.StringReader;
46 import java.io.InputStream;
47 import java.io.FileNotFoundException;
48 import java.util.Set;
49 import java.util.Iterator;
50 import java.util.Properties;
51 import java.util.Hashtable;
52
53 import javax.xml.parsers.DocumentBuilder;
54 import javax.xml.parsers.DocumentBuilderFactory;
55
56
57 /***
58 * Test for XSLTLayout.
59 *
60 */
61 public class XSLTLayoutTest extends LayoutTest {
62 /***
63 * Construct new instance of XSLTLayoutTest.
64 *
65 * @param testName test name.
66 */
67 public XSLTLayoutTest(final String testName) {
68 super(testName, "text/plain", false, null, null);
69 }
70
71 /***
72 * @{inheritDoc}
73 */
74 protected Layout createLayout() {
75 return new XSLTLayout();
76 }
77
78 /***
79 * Parses the string as the body of an XML document and returns the document element.
80 * @param source source string.
81 * @return document element.
82 * @throws Exception if parser can not be constructed or source is not a valid XML document.
83 */
84 private Element parse(final String source) throws Exception {
85 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
86 factory.setNamespaceAware(false);
87 factory.setCoalescing(true);
88
89 DocumentBuilder builder = factory.newDocumentBuilder();
90 Reader reader = new StringReader(source);
91 Document doc = builder.parse(new InputSource(reader));
92
93 return doc.getDocumentElement();
94 }
95
96 /***
97 * Checks a log4j:event element against expectations.
98 * @param element element, may not be null.
99 * @param event event, may not be null.
100 */
101 private void checkEventElement(
102 final Element element, final LoggingEvent event) {
103 assertEquals("log4j:event", element.getTagName());
104 assertEquals(
105 "org.apache.log4j.xml.XSLTLayoutTest", element.getAttribute("logger"));
106 assertEquals(
107 Long.toString(event.timeStamp), element.getAttribute("timestamp"));
108 assertEquals("INFO", element.getAttribute("level"));
109 assertEquals(event.getThreadName(), element.getAttribute("thread"));
110 }
111
112 /***
113 * Checks a log4j:message element against expectations.
114 * @param element element, may not be null.
115 * @param message expected message.
116 */
117 private void checkMessageElement(
118 final Element element, final String message) {
119 assertEquals("log4j:message", element.getTagName());
120
121 Node messageNode = element.getFirstChild();
122 assertNotNull(messageNode);
123 assertEquals(Node.TEXT_NODE, messageNode.getNodeType());
124 assertEquals(message, messageNode.getNodeValue());
125 assertNull(messageNode.getNextSibling());
126 }
127
128 /***
129 * Checks a log4j:message element against expectations.
130 * @param element element, may not be null.
131 * @param message expected message.
132 */
133 private void checkNDCElement(final Element element, final String message) {
134 assertEquals("log4j:NDC", element.getTagName());
135
136 Node messageNode = element.getFirstChild();
137 assertNotNull(messageNode);
138 assertEquals(Node.TEXT_NODE, messageNode.getNodeType());
139 assertEquals(message, messageNode.getNodeValue());
140 assertNull(messageNode.getNextSibling());
141 }
142
143 /***
144 * Checks a log4j:throwable element against expectations.
145 * @param element element, may not be null.
146 * @param ex exception, may not be null.
147 */
148 private void checkThrowableElement(
149 final Element element, final Exception ex) {
150 assertEquals("log4j:throwable", element.getTagName());
151
152 Node messageNode = element.getFirstChild();
153 assertNotNull(messageNode);
154 assertEquals(Node.TEXT_NODE, messageNode.getNodeType());
155
156 String msg = ex.toString();
157 assertEquals("Got " + messageNode.getNodeValue(), msg, messageNode.getNodeValue().substring(0, msg.length()));
158 assertNull(messageNode.getNextSibling());
159 }
160
161 /***
162 * Tests formatted results.
163 * @throws Exception if parser can not be constructed or source is not a valid XML document.
164 */
165 public void testFormat() throws Exception {
166 clearMDC();
167 NDC.clear();
168 Logger logger = Logger.getLogger("org.apache.log4j.xml.XSLTLayoutTest");
169 LoggingEvent event =
170 new LoggingEvent(
171 "org.apache.log4j.Logger", logger, Level.INFO, "Hello, World", null);
172 XSLTLayout layout = (XSLTLayout) createLayout();
173 String result = layout.format(event);
174 Element parsedResult = parse(result);
175 checkEventElement(parsedResult, event);
176
177 int childElementCount = 0;
178
179 for (
180 Node node = parsedResult.getFirstChild(); node != null;
181 node = node.getNextSibling()) {
182 switch (node.getNodeType()) {
183 case Node.ELEMENT_NODE:
184 childElementCount++;
185 checkMessageElement((Element) node, "Hello, World");
186
187 break;
188
189 case Node.COMMENT_NODE:
190 break;
191
192 case Node.TEXT_NODE:
193
194
195 break;
196
197 default:
198 fail("Unexpected node type");
199
200 break;
201 }
202 }
203
204 assertEquals(1, childElementCount);
205 }
206
207 /***
208 * Tests formatted results with an exception.
209 * @throws Exception if parser can not be constructed or source is not a valid XML document.
210 */
211 public void testFormatWithException() throws Exception {
212 clearMDC();
213 NDC.clear();
214 Logger logger = Logger.getLogger("org.apache.log4j.xml.XSLTLayoutTest");
215 Exception ex = new IllegalArgumentException("'foo' is not a valid name");
216 LoggingEvent event =
217 new LoggingEvent(
218 "org.apache.log4j.Logger", logger, Level.INFO, "Hello, World", ex);
219 XSLTLayout layout = (XSLTLayout) createLayout();
220 String result = layout.format(event);
221 Element parsedResult = parse(result);
222 checkEventElement(parsedResult, event);
223
224 int childElementCount = 0;
225
226 for (
227 Node node = parsedResult.getFirstChild(); node != null;
228 node = node.getNextSibling()) {
229 switch (node.getNodeType()) {
230 case Node.ELEMENT_NODE:
231 childElementCount++;
232
233 if (childElementCount == 1) {
234 checkMessageElement((Element) node, "Hello, World");
235 } else {
236 checkThrowableElement((Element) node, ex);
237 }
238
239 break;
240
241 case Node.COMMENT_NODE:
242 break;
243
244 case Node.TEXT_NODE:
245
246
247 break;
248
249 default:
250 fail("Unexpected node type");
251
252 break;
253 }
254 }
255
256 assertEquals(2, childElementCount);
257 }
258
259 /***
260 * Tests formatted results with an exception.
261 * @throws Exception if parser can not be constructed or source is not a valid XML document.
262 */
263 public void testFormatWithNDC() throws Exception {
264 clearMDC();
265 NDC.clear();
266 Logger logger = Logger.getLogger("org.apache.log4j.xml.XSLTLayoutTest");
267 NDC.push("NDC goes here");
268
269 LoggingEvent event =
270 new LoggingEvent(
271 "org.apache.log4j.Logger", logger, Level.INFO, "Hello, World", null);
272 XSLTLayout layout = (XSLTLayout) createLayout();
273 String result = layout.format(event);
274 NDC.pop();
275
276 Element parsedResult = parse(result);
277 checkEventElement(parsedResult, event);
278
279 int childElementCount = 0;
280
281 for (
282 Node node = parsedResult.getFirstChild(); node != null;
283 node = node.getNextSibling()) {
284 switch (node.getNodeType()) {
285 case Node.ELEMENT_NODE:
286 childElementCount++;
287
288 if (childElementCount == 1) {
289 checkMessageElement((Element) node, "Hello, World");
290 } else {
291 checkNDCElement((Element) node, "NDC goes here");
292 }
293
294 break;
295
296 case Node.COMMENT_NODE:
297 break;
298
299 case Node.TEXT_NODE:
300
301
302 break;
303
304 default:
305 fail("Unexpected node type");
306
307 break;
308 }
309 }
310
311 assertEquals(2, childElementCount);
312 }
313
314 /***
315 * Tests getLocationInfo and setLocationInfo.
316 */
317 public void testGetSetLocationInfo() {
318 XSLTLayout layout = new XSLTLayout();
319 assertEquals(false, layout.getLocationInfo());
320 layout.setLocationInfo(true);
321 assertEquals(true, layout.getLocationInfo());
322 layout.setLocationInfo(false);
323 assertEquals(false, layout.getLocationInfo());
324 }
325
326 /***
327 * Tests activateOptions().
328 */
329 public void testActivateOptions() {
330 XSLTLayout layout = new XSLTLayout();
331 layout.activateOptions();
332 }
333
334 /***
335 * Tests XML configuration and atom layout.
336 */
337 public void testAtom() throws Exception {
338 InputStream is =
339 XSLTLayoutTest.class.getResourceAsStream("xsltLayout4.xml");
340 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
341 factory.setNamespaceAware(false);
342 DocumentBuilder builder = factory.newDocumentBuilder();
343 Document doc = builder.parse(is);
344 org.apache.log4j.extras.DOMConfigurator.configure(
345 doc.getDocumentElement());
346 Logger logger = Logger.getLogger("org.apache.log4j.xml.XSLTLayoutTest");
347 logger.debug("DEBUG message");
348 logger.info("INFO message");
349 Transformer.transform(
350 "temp", "filtered",
351 new Filter[] { new LineNumberFilter(),
352 new JunitTestRunnerFilter(),
353 new XMLTimestampFilter(),
354 new XMLDateFilter()});
355 assertTrue(Compare.compare(XSLTLayoutTest.class,
356 "filtered", "witness/xml/xsltLayout.4"));
357 }
358
359 /***
360 * Tests XML configuration and atom layout.
361 */
362 public void testAtomNS() throws Exception {
363 InputStream is =
364 XSLTLayoutTest.class.getResourceAsStream("xsltLayout4.xml");
365 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
366 factory.setNamespaceAware(true);
367 DocumentBuilder builder = factory.newDocumentBuilder();
368 Document doc = builder.parse(is);
369 org.apache.log4j.extras.DOMConfigurator.configure(
370 doc.getDocumentElement());
371 Logger logger = Logger.getLogger("org.apache.log4j.xml.XSLTLayoutTest");
372 logger.debug("DEBUG message");
373 logger.info("INFO message");
374 Transformer.transform(
375 "temp", "filtered",
376 new Filter[] { new LineNumberFilter(),
377 new JunitTestRunnerFilter(),
378 new XMLTimestampFilter(),
379 new XMLDateFilter()});
380 assertTrue(Compare.compare(XSLTLayoutTest.class,
381 "filtered", "witness/xml/xsltLayout.4"));
382 }
383
384 /***
385 * Tests CDATA element within NDC content. See bug 37560.
386 */
387 public void testNDCWithCDATA() throws Exception {
388 Logger logger = Logger.getLogger("com.example.bar");
389 Level level = Level.INFO;
390 String ndcMessage ="<envelope><faultstring><![CDATA[The EffectiveDate]]></faultstring><envelope>";
391 NDC.push(ndcMessage);
392 LoggingEvent event =
393 new LoggingEvent(
394 "com.example.bar", logger, level, "Hello, World", null);
395 Layout layout = createLayout();
396 String result = layout.format(event);
397 NDC.clear();
398 Element parsedResult = parse(result);
399 NodeList ndcs = parsedResult.getElementsByTagName("log4j:NDC");
400 assertEquals(1, ndcs.getLength());
401 StringBuffer buf = new StringBuffer();
402 for(Node child = ndcs.item(0).getFirstChild();
403 child != null;
404 child = child.getNextSibling()) {
405 buf.append(child.getNodeValue());
406 }
407 assertEquals(ndcMessage, buf.toString());
408
409 }
410
411 /***
412 * Tests CDATA element within exception. See bug 37560.
413 */
414 public void testExceptionWithCDATA() throws Exception {
415 Logger logger = Logger.getLogger("com.example.bar");
416 Level level = Level.INFO;
417 String exceptionMessage ="<envelope><faultstring><![CDATA[The EffectiveDate]]></faultstring><envelope>";
418 LoggingEvent event =
419 new LoggingEvent(
420 "com.example.bar", logger, level, "Hello, World", new Exception(exceptionMessage));
421 Layout layout = createLayout();
422 String result = layout.format(event);
423 Element parsedResult = parse(result);
424 NodeList throwables = parsedResult.getElementsByTagName("log4j:throwable");
425 assertEquals(1, throwables.getLength());
426 StringBuffer buf = new StringBuffer();
427 for(Node child = throwables.item(0).getFirstChild();
428 child != null;
429 child = child.getNextSibling()) {
430 buf.append(child.getNodeValue());
431 }
432 assertTrue(buf.toString().indexOf(exceptionMessage) != -1);
433 }
434
435
436 private static void clearMDC() {
437 Hashtable context = MDC.getContext();
438 if (context != null) {
439 context.clear();
440 }
441 }
442 }