cvs commit: jakarta-log4j/tests/src/java/org/apache/log4j/xml XMLLayoutTestCase.java
[email protected] 11 Jun 2002 13:20:05 -0000
| Newsgroups | gmane.comp.jakarta.log4j.cvs |
|---|---|
| Message-ID | <[email protected]> |
ceki 2002/06/11 06:20:05
Modified: src/java/org/apache/log4j/xml Tag: v1_2-branch
XMLLayout.java
src/java/org/apache/log4j/helpers Tag: v1_2-branch
Transform.java
tests/src/java/org/apache/log4j/xml Tag: v1_2-branch
XMLLayoutTestCase.java
Log:
XMLLayout can now output messages which contain embedded CDATA
sections. This resolves bug #9750. Many thanks Michael
A. McAngus for supplying the relevant patch.
Added a new test in XMLLayoutTestCase.java
Revision Changes Path
No revision
No revision
1.18.2.2 +86 -88 jakarta-log4j/src/java/org/apache/log4j/xml/XMLLayout.java
Index: XMLLayout.java
===================================================================
RCS file: /home/cvs/jakarta-log4j/src/java/org/apache/log4j/xml/XMLLayout.java,v
retrieving revision 1.18.2.1
retrieving revision 1.18.2.2
diff -u -r1.18.2.1 -r1.18.2.2
--- XMLLayout.java 28 May 2002 14:25:00 -0000 1.18.2.1
+++ XMLLayout.java 11 Jun 2002 13:20:05 -0000 1.18.2.2
@@ -17,37 +17,38 @@
import org.apache.log4j.helpers.Transform;
/**
- The output of the XMLLayout consists of a series of log4j:event
- elements as defined in the <a
- href="doc-files/log4j.dtd">log4j.dtd</a>. It does not output a
- complete well-formed XML file. The output is designed to be
- included as an <em>external entity</em> in a separate file to form
- a correct XML file.
-
- <p>For example, if <code>abc</code> is the name of the file where
- the XMLLayout ouput goes, then a well-formed XML file would be:
-
- <pre>
+ * The output of the XMLLayout consists of a series of log4j:event
+ * elements as defined in the <a
+ * href="doc-files/log4j.dtd">log4j.dtd</a>. It does not output a
+ * complete well-formed XML file. The output is designed to be
+ * included as an <em>external entity</em> in a separate file to form
+ * a correct XML file.
+ *
+ * <p>For example, if <code>abc</code> is the name of the file where
+ * the XMLLayout ouput goes, then a well-formed XML file would be:
+ *
+ <pre>
<?xml version="1.0" ?>
-
- <!DOCTYPE log4j:eventSet SYSTEM "log4j.dtd" [<!ENTITY data SYSTEM "abc">]>
-
- <log4j:eventSet version="1.2" xmlns:log4j="http://jakarta.apache.org/log4j/">
- &data;
- </log4j:eventSet>
- </pre>
-
- <p>This approach enforces the independence of the XMLLayout and the
- appender where it is embedded.
-
- <p>The <code>version</code> attribute helps components to correctly
- intrepret output generated by XMLLayout. The value of this
- attribute should be "1.1" for output generated by log4j versions
- prior to log4j 1.2 (final release) and "1.2" for relase 1.2 and
- later.
-
- @author Ceki Gülcü
- @since 0.9.0 */
+
+ <!DOCTYPE log4j:eventSet SYSTEM "log4j.dtd" [<!ENTITY data SYSTEM "abc">]>
+
+ <log4j:eventSet version="1.2" xmlns:log4j="http://jakarta.apache.org/log4j/">
+ &data;
+ </log4j:eventSet>
+ </pre>
+
+ * <p>This approach enforces the independence of the XMLLayout and the
+ * appender where it is embedded.
+ *
+ * <p>The <code>version</code> attribute helps components to correctly
+ * intrepret output generated by XMLLayout. The value of this
+ * attribute should be "1.1" for output generated by log4j versions
+ * prior to log4j 1.2 (final release) and "1.2" for relase 1.2 and
+ * later.
+ *
+ * @author Ceki Gülcü
+ * @since 0.9.0
+ * */
public class XMLLayout extends Layout {
private final int DEFAULT_SIZE = 256;
@@ -55,41 +56,38 @@
private StringBuffer buf = new StringBuffer(DEFAULT_SIZE);
private boolean locationInfo = false;
-
/**
- The <b>LocationInfo</b> option takes a boolean value. By
- default, it is set to false which means there will be no location
- information output by this layout. If the the option is set to
- true, then the file name and line number of the statement
- at the origin of the log statement will be output.
-
- <p>If you are embedding this layout within an {@link
- org.apache.log4j.net.SMTPAppender} then make sure to set the
- <b>LocationInfo</b> option of that appender as well.
- */
- public
- void setLocationInfo(boolean flag) {
+ * The <b>LocationInfo</b> option takes a boolean value. By default,
+ * it is set to false which means there will be no location
+ * information output by this layout. If the the option is set to
+ * true, then the file name and line number of the statement at the
+ * origin of the log statement will be output.
+ *
+ * <p>If you are embedding this layout within an {@link
+ * org.apache.log4j.net.SMTPAppender} then make sure to set the
+ * <b>LocationInfo</b> option of that appender as well.
+ * */
+ public void setLocationInfo(boolean flag) {
locationInfo = flag;
}
/**
Returns the current value of the <b>LocationInfo</b> option.
*/
- public
- boolean getLocationInfo() {
+ public boolean getLocationInfo() {
return locationInfo;
}
- public
- void activateOptions() {
+ /** No options to activate. */
+ public void activateOptions() {
}
/**
- Formats a {@link LoggingEvent} in conformance with the log4j.dtd. */
- public
- String format(LoggingEvent event) {
+ * Formats a {@link LoggingEvent} in conformance with the log4j.dtd.
+ * */
+ public String format(LoggingEvent event) {
// Reset working buffer. If the buffer is too large, then we need a new
// one in order to avoid the penalty of creating a large array.
@@ -111,43 +109,44 @@
buf.append(event.getThreadName());
buf.append("\">\r\n");
-
- buf.append("<log4j:message><![CDATA[");
- buf.append(event.getRenderedMessage());
- buf.append("]]></log4j:message>\r\n");
-
- String ndc = event.getNDC();
- if(ndc != null) {
- buf.append("<log4j:NDC><![CDATA[");
- buf.append(ndc);
- buf.append("]]></log4j:NDC>\r\n");
- }
-
- String[] s = event.getThrowableStrRep();
- if(s != null) {
- buf.append("<log4j:throwable><![CDATA[");
- for(int i = 0; i < s.length; i++) {
- buf.append(s[i]);
- buf.append("\r\n");
- }
- buf.append("]]></log4j:throwable>\r\n");
- }
-
- if(locationInfo) {
- LocationInfo locationInfo = event.getLocationInformation();
- buf.append("<log4j:locationInfo class=\"");
- buf.append(locationInfo.getClassName());
- buf.append("\" method=\"");
- buf.append(Transform.escapeTags(locationInfo.getMethodName()));
- buf.append("\" file=\"");
- buf.append(locationInfo.getFileName());
- buf.append("\" line=\"");
- buf.append(locationInfo.getLineNumber());
- buf.append("\"/>\r\n");
- }
-
+ buf.append("<log4j:message><![CDATA[");
+ // Append the rendered message. Also make sure to escape any
+ // existing CDATA sections.
+ Transform.appendEscapingCDATA(buf, event.getRenderedMessage());
+ buf.append("]]></log4j:message>\r\n");
+
+ String ndc = event.getNDC();
+ if(ndc != null) {
+ buf.append("<log4j:NDC><![CDATA[");
+ buf.append(ndc);
+ buf.append("]]></log4j:NDC>\r\n");
+ }
+
+ String[] s = event.getThrowableStrRep();
+ if(s != null) {
+ buf.append("<log4j:throwable><![CDATA[");
+ for(int i = 0; i < s.length; i++) {
+ buf.append(s[i]);
+ buf.append("\r\n");
+ }
+ buf.append("]]></log4j:throwable>\r\n");
+ }
+
+ if(locationInfo) {
+ LocationInfo locationInfo = event.getLocationInformation();
+ buf.append("<log4j:locationInfo class=\"");
+ buf.append(locationInfo.getClassName());
+ buf.append("\" method=\"");
+ buf.append(Transform.escapeTags(locationInfo.getMethodName()));
+ buf.append("\" file=\"");
+ buf.append(locationInfo.getFileName());
+ buf.append("\" line=\"");
+ buf.append(locationInfo.getLineNumber());
+ buf.append("\"/>\r\n");
+ }
+
buf.append("</log4j:event>\r\n\r\n");
-
+
return buf.toString();
}
@@ -155,8 +154,7 @@
The XMLLayout prints and does not ignore exceptions. Hence the
return value <code>false</code>.
*/
- public
- boolean ignoresThrowable() {
+ public boolean ignoresThrowable() {
return false;
}
}
No revision
No revision
1.1.2.1 +47 -8 jakarta-log4j/src/java/org/apache/log4j/helpers/Transform.java
Index: Transform.java
===================================================================
RCS file: /home/cvs/jakarta-log4j/src/java/org/apache/log4j/helpers/Transform.java,v
retrieving revision 1.1
retrieving revision 1.1.2.1
diff -u -r1.1 -r1.1.2.1
--- Transform.java 26 Apr 2002 12:31:42 -0000 1.1
+++ Transform.java 11 Jun 2002 13:20:05 -0000 1.1.2.1
@@ -12,21 +12,28 @@
/**
Utility class for transforming strings.
+
+ @author Ceki Gülcü
+ @author Michael A. McAngus
*/
public class Transform {
+ private static final String CDATA_START = "<![CDATA[";
+ private static final String CDATA_END = "]]>";
+ private static final String CDATA_PSEUDO_END = "]]>";
+ private static final String CDATA_EMBEDED_END = CDATA_END + CDATA_PSEUDO_END + CDATA_START;
+ private static final int CDATA_END_LEN = CDATA_END.length();
+
/**
- * This method takes a string which may contain HTML tags (ie, <b>, <table>,
- * etc) and converts the '<' and '>' characters to their HTML escape
- * sequences.
+ * This method takes a string which may contain HTML tags (ie,
+ * <b>, <table>, etc) and replaces any '<' and '>'
+ * characters with respective predefined entity references.
*
* @param input The text to be converted.
* @return The input string with the characters '<' and '>' replaced with
- * < and > respectively.
- */
- static
- public
- String escapeTags(String input) {
+ * &lt; and &gt; respectively.
+ * */
+ static public String escapeTags(String input) {
//Check if the string is null or zero length -- if so, return
//what was sent in.
@@ -52,5 +59,37 @@
}
}
return buf.toString();
+ }
+
+ /**
+ * Ensures that embeded CDEnd strings (]]>) are handled properly
+ * within message, NDC and throwable tag text.
+ *
+ * @param buf StringBuffer holding the XML data to this point. The
+ * initial CDStart (<![CDATA[) and final CDEnd (]]>) of the CDATA
+ * section are the responsibility of the calling method.
+ * @param str The String that is inserted into an existing CDATA Section within buf.
+ * */
+ static public void appendEscapingCDATA(StringBuffer buf, String str) {
+ int end = str.indexOf(CDATA_END);
+
+ if (end < 0) {
+ buf.append(str);
+ return;
+ }
+
+ int start = 0;
+ while (end > -1) {
+ buf.append(str.substring(start,end));
+ buf.append(CDATA_EMBEDED_END);
+ start = end + CDATA_END_LEN;
+ if (start < str.length()) {
+ end = str.indexOf(CDATA_END, start);
+ } else {
+ return;
+ }
+ }
+
+ buf.append(str.substring(start));
}
}
No revision
No revision
1.2.2.1 +14 -1 jakarta-log4j/tests/src/java/org/apache/log4j/xml/XMLLayoutTestCase.java
Index: XMLLayoutTestCase.java
===================================================================
RCS file: /home/cvs/jakarta-log4j/tests/src/java/org/apache/log4j/xml/XMLLayoutTestCase.java,v
retrieving revision 1.2
retrieving revision 1.2.2.1
diff -u -r1.2 -r1.2.2.1
--- XMLLayoutTestCase.java 29 Apr 2002 14:41:23 -0000 1.2
+++ XMLLayoutTestCase.java 11 Jun 2002 13:20:05 -0000 1.2.2.1
@@ -58,6 +58,19 @@
assertTrue(Compare.compare(FILTERED, "witness/xmlLayout.2"));
}
+ public void testCDATA() throws Exception {
+ XMLLayout xmlLayout = new XMLLayout();
+ xmlLayout.setLocationInfo(true);
+ root.addAppender(new FileAppender(xmlLayout, TEMP, false));
+
+ logger.debug("Message with embedded <![CDATA[<hello>hi</hello>]]>.");
+
+ Transformer.transform(TEMP, FILTERED, new Filter[] {new LineNumberFilter(),
+ new XMLTimestampFilter(),
+ new XMLLineAttributeFilter()});
+ assertTrue(Compare.compare(FILTERED, "witness/xmlLayout.3"));
+ }
+
void common() {
int i = -1;
@@ -84,13 +97,13 @@
logger.error("Message " + ++i, e);
root.error("Message " + i, e);
-
}
public static Test suite() {
TestSuite suite = new TestSuite();
suite.addTest(new XMLLayoutTestCase("basic"));
suite.addTest(new XMLLayoutTestCase("locationInfo"));
+ suite.addTest(new XMLLayoutTestCase("testCDATA"));
return suite;
}