package com.runjva.logback.xml;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import ch.qos.logback.classic.pattern.ClassOfCallerConverter;
import ch.qos.logback.classic.pattern.FileOfCallerConverter;
import ch.qos.logback.classic.pattern.LineOfCallerConverter;
import ch.qos.logback.classic.pattern.MethodOfCallerConverter;
import ch.qos.logback.classic.spi.LoggingEvent;
import ch.qos.logback.classic.spi.ThrowableDataPoint;
import ch.qos.logback.classic.spi.ThrowableProxy;
import ch.qos.logback.core.CoreConstants;
/**
*
* XMLLayout creates XML fragments conforming to the log4j.dtd from the Apache
* log4j project, and generates output compatible with the log4j XMLLayout
* class. Files written with this layout are readable by Chainsaw (note that
* output is in 7-bit ASCII so encoding should not be a problem).
*
*
* The physical layout is intended to be somewhat readable by human eyes. Each
* event generates two lines. The first starts with
*
*
* <log4j:event time='2009-02-04 13:00:16,650' logger='com.runjva.logback.xml.XMLLayoutMain'
*
*
* where the time attribute (which is valid but unused in the log4j XMLLayout)
* is used to render a humanly readable form of the timestamp in the ISO8601
* pattern used in PatternLayout dates. The second line starts with
*
*
* <log4j:message>A debug message</log4j:message>
*
*
* which is the message with a prefix common to all lines giving the same
* indention hopefully making it readable to the human eye.
*
*
*/
public class XMLLayout extends ch.qos.logback.core.LayoutBase {
// The following attributes are listed on
// http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/xml/XMLLayout.html
boolean locationInfo = true;
boolean properties = true;
DateFormat simpleFormat = new SimpleDateFormat(
CoreConstants.ISO8601_PATTERN);
public String doLayout(LoggingEvent event) {
/*
* Hey you!
*
*/
java.util.Date then = new java.util.Date(event.getTimeStamp());
StringBuffer sb = new StringBuffer();
sb.append("");
sb.append("\n");
sb.append("");
sb.append(q(event.getFormattedMessage()));
sb.append("");
//
// not available in slf4j
// #CONTENT is lines separated with \n
ThrowableProxy throwableProxy = event.getThrowableProxy();
if (throwableProxy != null) {
sb.append("");
ThrowableDataPoint[] dataPoints;
dataPoints = throwableProxy.getThrowableDataPointArray();
for (int i = 0; i < dataPoints.length; i++) {
ThrowableDataPoint throwableDataPoint = dataPoints[i];
sb.append(q(throwableDataPoint.toString()));
sb.append(q("\n"));
}
sb.append("");
}
//
if (this.getLocationInfo()) {
sb.append("");
}
/*
*
*
*/
if (this.getProperties()) {
Map propertyMap = event.getMDCPropertyMap();
if (propertyMap != null) {
Set> entrySet = propertyMap.entrySet();
sb.append("");
for (Entry entry : entrySet) {
sb.append("");
}
sb.append("");
}
}
sb.append("\n");
// System.err.println(" << " + sb.toString());
return sb.toString();
}
public boolean getLocationInfo() {
return locationInfo;
}
/**
* setLocationInfo sets the locationInfo flag. If true each event layouted
* by XMLLayout include the file name and line number where the log event
* was created. If false, no location information is included-
*
* @param locationInfo
* new value to set
*/
public void setLocationInfo(boolean locationInfo) {
// System.out.println("locationInfo= " + locationInfo);
this.locationInfo = locationInfo;
}
public boolean getProperties() {
return properties;
}
/**
* setProperties sets the properties flag. If true each event layouted by
* XMLLayout include the complete set of key-value pairs in the MDC. If
* false, no MDC information is layouted.
*
* @param properties
*/
public void setProperties(boolean properties) {
// System.err.println("properties=" + properties);
this.properties = properties;
}
/**
* q quotes the string s so it can be used directly as an XML payload
* without worrying about reserved characters or character encodings as all
* non-ASCII characters plus those reserved in XML are rendered as
* &#entity; - e.g. renders & as #.
*
* @param s
* @return StringBuffer with a XML representation of s
*/
private StringBuffer q(String s) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
char ch = s.charAt(i);
if (ch < 32 || ch == '&' || ch == '<' || ch == '>' || ch > 126) {
sb.append("" + ((int) ch) + ";");
} else {
sb.append(ch);
}
}
return sb;
}
}