modify xml decoders so additionalProperties override existing properties (allows, for example, the ability to load a set of saved events into a new tab in chainsaw, because chainsaw can modify the application/hostname properties that control event routing).
Also fixed a bug in additional properties loading.
git-svn-id: https://svn.apache.org/repos/asf/logging/log4j/companions/receivers/trunk@829655 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/log4j/xml/UtilLoggingXMLDecoder.java b/src/main/java/org/apache/log4j/xml/UtilLoggingXMLDecoder.java
index 1c2244a..b36ffb6 100644
--- a/src/main/java/org/apache/log4j/xml/UtilLoggingXMLDecoder.java
+++ b/src/main/java/org/apache/log4j/xml/UtilLoggingXMLDecoder.java
@@ -122,14 +122,14 @@
* @param properties additional properties
*/
public void setAdditionalProperties(final Map properties) {
- this.additionalProperties.putAll(properties);
+ this.additionalProperties = properties;
}
/**
* Converts the LoggingEvent data in XML string format into an actual
* XML Document class instance.
* @param data XML fragment
- * @return XML document
+ * @return dom document
*/
private Document parse(final String data) {
if (docBuilder == null || data == null) {
@@ -188,15 +188,19 @@
}
Vector v = new Vector();
- String line = null;
- try {
- while ((line = reader.readLine()) != null) {
- StringBuffer buffer = new StringBuffer(line);
- for (int i = 0; i < 100; i++) {
- buffer.append(reader.readLine());
- }
- v.addAll(decodeEvents(buffer.toString()));
- }
+ String line;
+ Vector events;
+ try {
+ while ((line = reader.readLine()) != null) {
+ StringBuffer buffer = new StringBuffer(line);
+ for (int i = 0; i < 1000; i++) {
+ buffer.append(reader.readLine()).append("\n");
+ }
+ events = decodeEvents(buffer.toString());
+ if (events != null) {
+ v.addAll(events);
+ }
+ }
} finally {
partialEvent = null;
try {
@@ -220,14 +224,14 @@
if (document != null) {
- if (document.equals("")) {
+ if (document.trim().equals("")) {
return null;
}
String newDoc;
String newPartialEvent = null;
//separate the string into the last portion ending with </record>
- // (which willbe processed) and the partial event which
+ // (which will be processed) and the partial event which
// will be combined and processed in the next section
//if the document does not contain a record end,
@@ -286,7 +290,7 @@
/**
* Given a Document, converts the XML into a Vector of LoggingEvents.
* @param document XML document
- * @return vector of logging events
+ * @return Vector of LoggingEvents
*/
private Vector decodeEvents(final Document document) {
Vector events = new Vector();
@@ -298,17 +302,17 @@
Node eventNode = eventList.item(eventIndex);
Logger logger = null;
- long timeStamp = 0L;
- Level level = null;
- String threadName = null;
- Object message = null;
- String ndc = null;
- String[] exception = null;
- String className = null;
- String methodName = null;
- String fileName = null;
- String lineNumber = null;
- Hashtable properties = new Hashtable();
+ long timeStamp = 0L;
+ Level level = null;
+ String threadName = null;
+ Object message = null;
+ String ndc = null;
+ String[] exception = null;
+ String className = null;
+ String methodName = null;
+ String fileName = null;
+ String lineNumber = null;
+ Hashtable properties = new Hashtable();
//format of date: 2003-05-04T11:04:52
//ignore date or set as a property? using millis in constructor instead
@@ -382,25 +386,22 @@
}
}
- /**
- * We add all the additional properties to the properties
- * hashtable
- */
- if (additionalProperties.size() > 0) {
- if (properties == null) {
- properties = new Hashtable(additionalProperties);
- } else {
- Iterator i = additionalProperties.entrySet().iterator();
- while (i.hasNext()) {
- Map.Entry e = (Map.Entry) i.next();
- if (!(properties.containsKey(e.getKey()))) {
+ /**
+ * We add all the additional properties to the properties
+ * hashtable. Override properties that already exist
+ */
+ if (additionalProperties.size() > 0) {
+ if (properties == null) {
+ properties = new Hashtable(additionalProperties);
+ }
+ Iterator i = additionalProperties.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry e = (Map.Entry) i.next();
properties.put(e.getKey(), e.getValue());
}
- }
}
- }
- LocationInfo info = null;
+ LocationInfo info;
if ((fileName != null)
|| (className != null)
|| (methodName != null)
diff --git a/src/main/java/org/apache/log4j/xml/XMLDecoder.java b/src/main/java/org/apache/log4j/xml/XMLDecoder.java
index 0714563..13aa495 100644
--- a/src/main/java/org/apache/log4j/xml/XMLDecoder.java
+++ b/src/main/java/org/apache/log4j/xml/XMLDecoder.java
@@ -57,7 +57,7 @@
* even though the DTD supports multiple events nested in an eventSet.
*
* NOTE: This class has been created on the assumption that all XML log files
- * are encoding in UTF-8 encoding. There is no current support for any other
+ * are encoded in UTF-8. There is no current support for any other
* encoding format at this time.
*
* @author Scott Deboy (sdeboy@apache.org)
@@ -115,7 +115,6 @@
* Create new instance.
*/
public XMLDecoder() {
- super();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
@@ -156,7 +155,6 @@
// complain. Indeed, "log4j.dtd" alone is not a valid URI which
// causes Crimson to barf. The Log4jEntityResolver only cares
// about the "log4j.dtd" ending.
- // buf.setLength(0);
/**
* resetting the length of the StringBuffer is dangerous, particularly
@@ -274,7 +272,7 @@
* relevant bits to form a new LoggingEvent instance which can be used
* by any Log4j element locally.
* @param data XML fragment
- * @return a single LoggingEvent
+ * @return a single LoggingEvent or null
*/
public LoggingEvent decode(final String data) {
Document document = parse(data);
@@ -302,7 +300,7 @@
Logger logger;
long timeStamp;
- String level;
+ Level level;
String threadName;
Object message = null;
String ndc = null;
@@ -325,19 +323,18 @@
if (eventNode.getNodeType() != Node.ELEMENT_NODE) {
continue;
}
- logger =
- Logger.getLogger(
- eventNode.getAttributes().getNamedItem("logger").getNodeValue());
- timeStamp =
- Long.parseLong(
- eventNode.getAttributes().getNamedItem("timestamp").getNodeValue());
- level = eventNode.getAttributes().getNamedItem("level").getNodeValue();
- threadName =
- eventNode.getAttributes().getNamedItem("thread").getNodeValue();
+ logger = Logger.getLogger(eventNode.getAttributes().getNamedItem("logger").getNodeValue());
+ timeStamp = Long.parseLong(eventNode.getAttributes().getNamedItem("timestamp").getNodeValue());
+ level = Level.toLevel(eventNode.getAttributes().getNamedItem("level").getNodeValue());
+ threadName = eventNode.getAttributes().getNamedItem("thread").getNodeValue();
NodeList list = eventNode.getChildNodes();
int listLength = list.getLength();
+ if (listLength == 0) {
+ continue;
+ }
+
for (int y = 0; y < listLength; y++) {
String tagName = list.item(y).getNodeName();
@@ -406,25 +403,21 @@
}
}
- /**
- * We add all the additional properties to the properties
- * hashtable. Don't override properties that already exist
- */
- if (additionalProperties.size() > 0) {
- if (properties == null) {
- properties = new Hashtable(additionalProperties);
- } else {
- Iterator i = additionalProperties.entrySet().iterator();
- while (i.hasNext()) {
- Map.Entry e = (Map.Entry) i.next();
- if (!(properties.containsKey(e.getKey()))) {
- properties.put(e.getKey(), e.getValue());
+ /**
+ * We add all the additional properties to the properties
+ * hashtable. Override properties that already exist
+ */
+ if (additionalProperties.size() > 0) {
+ if (properties == null) {
+ properties = new Hashtable(additionalProperties);
}
- }
+ Iterator i = additionalProperties.entrySet().iterator();
+ while (i.hasNext()) {
+ Map.Entry e = (Map.Entry) i.next();
+ properties.put(e.getKey(), e.getValue());
+ }
}
- }
}
- Level levelImpl = Level.toLevel(level);
LocationInfo info;
if ((fileName != null)
@@ -440,7 +433,7 @@
}
LoggingEvent loggingEvent = new LoggingEvent(null,
- logger, timeStamp, levelImpl, message,
+ logger, timeStamp, level, message,
threadName,
new ThrowableInformation(exception),
ndc,