psmith 2003/06/24 01:08:44
Added: src/java/org/apache/log4j/xml UtilLoggingEntityResolver.java
logger.dtd UtilLoggingXMLDecoder.java
XMLDecoder.java
Log:
Additional files from the sandbox.
These XML classes are for decoding XML into events, or to deal
with java.util logging events.
Revision Changes Path
1.1
jakarta-log4j/src/java/org/apache/log4j/xml/UtilLoggingEntityResolver.java
Index: UtilLoggingEntityResolver.java
===================================================================
/*
* ============================================================================
* The Apache Software License, Version 1.1
* ============================================================================
*
* Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must
* include the following acknowledgment: "This product includes software
* developed by the Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The names "log4j" and "Apache Software Foundation" must not be used to
* endorse or promote products derived from this software without prior
* written permission. For written permission, please contact
* [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache", nor may
* "Apache" appear in their name, without prior written permission of the
* Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* on behalf of the Apache Software Foundation. For more information on the
* Apache Software Foundation, please see <http://www.apache.org/>.
*
*/
package org.apache.log4j.xml;
import java.io.InputStream;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.apache.log4j.helpers.LogLog;
/**
* An [EMAIL PROTECTED] EntityResolver} specifically designed to return
* <code>java 1.4's logging dtd, logger.dtd</code> which is embedded within the
log4j jar
* file. Based on EntityResolver.
*
* @author Paul Austin
* @author Scott Deboy <[EMAIL PROTECTED]>
*
*/
public class UtilLoggingEntityResolver implements EntityResolver {
public InputSource resolveEntity (String publicId, String systemId) {
System.err.println("publicID: ["+publicId+"]");
System.err.println("systemId: ["+systemId+"]");
if (systemId.endsWith("logger.dtd")) {
Class clazz = getClass();
InputStream in = clazz.getResourceAsStream("/org/apache/log4j/xml/logger.dtd");
if (in == null) {
LogLog.error("Could not find [logger.dtd]. Used [" + clazz.getClassLoader()
+ "] class loader in the search.");
return null;
} else {
return new InputSource(in);
}
} else {
return null;
}
}
}
1.1 jakarta-log4j/src/java/org/apache/log4j/xml/logger.dtd
Index: logger.dtd
===================================================================
<!-- DTD used by the java.util.logging.XMLFormatter -->
<!-- This provides an XML formatted log message. -->
<!-- The document type is "log" which consists of a sequence
of record elements -->
<!ELEMENT log (record*)>
<!-- Each logging call is described by a record element. -->
<!ELEMENT record (date, millis, sequence, logger?, level,
class?, method?, thread?, message, key?, catalog?, param*, exception?)>
<!-- Date and time when LogRecord was created in ISO 8601 format -->
<!ELEMENT date (#PCDATA)>
<!-- Time when LogRecord was created in milliseconds since
midnight January 1st, 1970, UTC. -->
<!ELEMENT millis (#PCDATA)>
<!-- Unique sequence number within source VM. -->
<!ELEMENT sequence (#PCDATA)>
<!-- Name of source Logger object. -->
<!ELEMENT logger (#PCDATA)>
<!-- Logging level, may be either one of the constant
names from java.util.logging.Constants (such as "SEVERE"
or "WARNING") or an integer value such as "20". -->
<!ELEMENT level (#PCDATA)>
<!-- Fully qualified name of class that issued
logging call, e.g. "javax.marsupial.Wombat". -->
<!ELEMENT class (#PCDATA)>
<!-- Name of method that issued logging call.
It may be either an unqualified method name such as
"fred" or it may include argument type information
in parenthesis, for example "fred(int,String)". -->
<!ELEMENT method (#PCDATA)>
<!-- Integer thread ID. -->
<!ELEMENT thread (#PCDATA)>
<!-- The message element contains the text string of a log message. -->
<!ELEMENT message (#PCDATA)>
<!-- If the message string was localized, the key element provides
the original localization message key. -->
<!ELEMENT key (#PCDATA)>
<!-- If the message string was localized, the catalog element provides
the logger's localization resource bundle name. -->
<!ELEMENT catalog (#PCDATA)>
<!-- If the message string was localized, each of the param elements
provides the String value (obtained using Object.toString())
of the corresponding LogRecord parameter. -->
<!ELEMENT param (#PCDATA)>
<!-- An exception consists of an optional message string followed
by a series of StackFrames. Exception elements are used
for Java exceptions and other java Throwables. -->
<!ELEMENT exception (message?, frame+)>
<!-- A frame describes one line in a Throwable backtrace. -->
<!ELEMENT frame (class, method, line?)>
<!-- an integer line number within a class's source file. -->
<!ELEMENT line (#PCDATA)>
1.1
jakarta-log4j/src/java/org/apache/log4j/xml/UtilLoggingXMLDecoder.java
Index: UtilLoggingXMLDecoder.java
===================================================================
/*
* ============================================================================
* The Apache Software License, Version 1.1
* ============================================================================
*
* Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must
* include the following acknowledgment: "This product includes software
* developed by the Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The names "log4j" and "Apache Software Foundation" must not be used to
* endorse or promote products derived from this software without prior
* written permission. For written permission, please contact
* [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache", nor may
* "Apache" appear in their name, without prior written permission of the
* Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* on behalf of the Apache Software Foundation. For more information on the
* Apache Software Foundation, please see <http://www.apache.org/>.
*
*/
package org.apache.log4j.xml;
import org.apache.log4j.Decoder;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.UtilLoggingLevel;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
/**
* Decodes JDK 1.4's java.util.logging package events delivered via XML (using the
logger.dtd).
*
* @author Scott Deboy <[EMAIL PROTECTED]>
* @author Paul Smith <[EMAIL PROTECTED]>
*
*/
public class UtilLoggingXMLDecoder implements Decoder {
//NOTE: xml section is only handed on first delivery of events
//on this first delivery of events, there is no end tag for the log element
private static final String BEGIN_PART =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><!DOCTYPE log SYSTEM
\"logger.dtd\"><log>";
private static final String END_PART= "</log>";
private DocumentBuilderFactory dbf;
private DocumentBuilder docBuilder;
private Map additionalProperties = new HashMap();
private String partialEvent;
private static final String RECORD_END="</record>";
public UtilLoggingXMLDecoder() {
dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
try {
docBuilder = dbf.newDocumentBuilder();
docBuilder.setErrorHandler(new SAXErrorHandler());
docBuilder.setEntityResolver(new UtilLoggingEntityResolver());
} catch (ParserConfigurationException pce) {
System.err.println("Unable to get document builder");
}
additionalProperties.put("log4j.eventtype", "util-logging");
}
/**
* Sets an additionalProperty map, where each Key/Value pair is
* automatically added to each LoggingEvent as it is decoded.
*
* This is useful, say, to include the source file name of the Logging events
* @param additionalProperties
*/
public void setAdditionalProperties(Map additionalProperties) {
this.additionalProperties.putAll(additionalProperties);
}
/**
* Converts the LoggingEvent data in XML string format into an actual
* XML Document class instance.
* @param data
* @return
*/
private Document parse(String data) {
if (docBuilder == null) {
return null;
}
Document document = null;
try {
// we change the system ID to a valid URI so that Crimson won't
// complain. Indeed, "log4j.dtd" alone is not a valid URI which
// causes Crimson to barf. The Log4jEntityResolver only cares
// about the "log4j.dtd" ending.
/**
* resetting the length of the StringBuffer is dangerous, particularly
* on some JDK 1.4 impls, there's a known Bug that causes a memory leak
*/
if (data != null) {
data = data.trim();
}
StringBuffer buf = new StringBuffer(1024);
if (!data.startsWith("<?xml")) {
buf.append(BEGIN_PART);
}
buf.append(data);
if (!data.endsWith(END_PART)) {
buf.append(END_PART);
}
InputSource inputSource =
new InputSource(new StringReader(buf.toString()));
inputSource.setSystemId("dummy://logger.dtd");
document = docBuilder.parse(inputSource);
} catch (Exception e) {
e.printStackTrace();
}
return document;
}
/**
* Reads the contents of the file into a String
* @param file the file to load
* @return The contents of the file as a String
* @throws IOException if an error occurred during the loading process
*/
private String loadFileSource(File file) throws IOException {
LineNumberReader reader = null;
StringBuffer buf = new StringBuffer(1024);
try {
reader = new LineNumberReader(new FileReader(file));
String line = null;
while ((line = reader.readLine()) != null) {
buf.append(line);
}
} catch (IOException e) {
throw e;
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (Exception e) {
}
}
return buf.toString();
}
/**
* Decodes a File into a Vector of LoggingEvents
* @param file the file to decode events from
* @return Vector of LoggingEvents
* @throws IOException
*/
public Vector decode(File file) throws IOException {
String fileContents = loadFileSource(file);
Document doc = parse(fileContents);
if (doc == null) {
return null;
}
return decodeEvents(doc);
}
/**
* Decodes a String with possibly multiple events into a Vector of LoggingEvents
* @param String to decode events from
* @return Vector of LoggingEvents
*/
public Vector decodeEvents(String document) {
if (document != null) {
document = document.trim();
if (document.equals("")) {
return null;
} else {
String newDoc=null;
String newPartialEvent=null;
//separate the string into the last portion ending with </record>
(which will
//be processed) and the partial event which will be combined and
processed in the next section
if (document.lastIndexOf(RECORD_END) + RECORD_END.length() <
document.length()) {
newDoc = document.substring(0, document.lastIndexOf(RECORD_END) +
RECORD_END.length());
newPartialEvent =
document.substring(document.lastIndexOf(RECORD_END) + RECORD_END.length());
} else {
newDoc = document;
}
if (partialEvent != null) {
newDoc=partialEvent + newDoc;
}
partialEvent=newPartialEvent;
Document doc = parse(newDoc);
if (doc == null) {
return null;
}
return decodeEvents(doc);
}
}
return null;
}
/**
* Converts the string data into an XML Document, and then soaks out the
* relevant bits to form a new LoggingEvent instance which can be used
* by any Log4j element locally.
* @param data
* @return a single LoggingEvent
*/
public LoggingEvent decode(String data) {
Document document = parse(data);
if (document == null) {
return null;
}
Vector events = decodeEvents(document);
if (events.size() > 0) {
return (LoggingEvent) events.firstElement();
}
return null;
}
/**
* Given a Document, converts the XML into a Vector of LoggingEvents
* @param document
* @return
*/
private Vector decodeEvents(Document document) {
Vector events = new Vector();
NodeList eventList = document.getElementsByTagName("record");
for (int eventIndex = 0; eventIndex < eventList.getLength();
eventIndex++) {
Node eventNode = eventList.item(eventIndex);
Logger logger = null;
long timeStamp = 0L;
Level level = null;
String threadName = null;
Object message = null;
String ndc = null;
Hashtable mdc = 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
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();
if (tagName.equalsIgnoreCase("logger")) {
logger = Logger.getLogger(getCData(list.item(y)));
}
if (tagName.equalsIgnoreCase("millis")) {
timeStamp = Long.parseLong(getCData(list.item(y)));
}
if (tagName.equalsIgnoreCase("level")) {
level = UtilLoggingLevel.toLevel(getCData(list.item(y)));
}
if (tagName.equalsIgnoreCase("thread")) {
threadName = getCData(list.item(y));
}
if (tagName.equalsIgnoreCase("sequence")) {
properties.put("log4jid", getCData(list.item(y)));
}
if (tagName.equalsIgnoreCase("message")) {
message = getCData(list.item(y));
}
if (tagName.equalsIgnoreCase("class")) {
className = getCData(list.item(y));
}
if (tagName.equalsIgnoreCase("method")) {
methodName = getCData(list.item(y));
}
if (tagName.equalsIgnoreCase("exception")) {
ArrayList exceptionList = new ArrayList();
NodeList exList = list.item(y).getChildNodes();
int exlistLength = exList.getLength();
for (int i2 = 0; i2 < exlistLength; i2++) {
Node exNode = exList.item(i2);
String exName = exList.item(i2).getNodeName();
if (exName.equalsIgnoreCase("message")) {
exceptionList.add(getCData(exList.item(i2)));
}
if (exName.equalsIgnoreCase("frame")) {
NodeList exList2 = exNode.getChildNodes();
int exlist2Length = exList2.getLength();
for (int i3 = 0; i3 < exlist2Length; i3++) {
exceptionList.add(getCData(exList2.item(i3)) + "\n");
}
}
}
exception =
(String[]) exceptionList.toArray(new String[exceptionList.size()]);
}
}
/**
* We add all the additional properties to the properties
* hashtable
*/
if (additionalProperties.size() > 0) {
if (properties == null) {
properties = new Hashtable(additionalProperties);
} else {
properties.putAll(additionalProperties);
}
}
events.add(
new LoggingEvent(
logger.getName(), logger, timeStamp, level, threadName, message, ndc,
mdc, exception,
new LocationInfo(fileName, className, methodName, lineNumber),
properties));
}
return events;
}
private String getCData(Node n) {
StringBuffer buf = new StringBuffer();
NodeList nl = n.getChildNodes();
for (int x = 0; x < nl.getLength(); x++) {
Node innerNode = nl.item(x);
if (
(innerNode.getNodeType() == Node.TEXT_NODE)
|| (innerNode.getNodeType() == Node.CDATA_SECTION_NODE)) {
buf.append(innerNode.getNodeValue());
}
}
return buf.toString();
}
}
1.1 jakarta-log4j/src/java/org/apache/log4j/xml/XMLDecoder.java
Index: XMLDecoder.java
===================================================================
/*
* ============================================================================
* The Apache Software License, Version 1.1
* ============================================================================
*
* Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modifica-
* tion, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The end-user documentation included with the redistribution, if any, must
* include the following acknowledgment: "This product includes software
* developed by the Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself, if
* and wherever such third-party acknowledgments normally appear.
*
* 4. The names "log4j" and "Apache Software Foundation" must not be used to
* endorse or promote products derived from this software without prior
* written permission. For written permission, please contact
* [EMAIL PROTECTED]
*
* 5. Products derived from this software may not be called "Apache", nor may
* "Apache" appear in their name, without prior written permission of the
* Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* APACHE SOFTWARE FOUNDATION OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLU-
* DING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* on behalf of the Apache Software Foundation. For more information on the
* Apache Software Foundation, please see <http://www.apache.org/>.
*
*/
package org.apache.log4j.xml;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.LineNumberReader;
import java.io.StringReader;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Map;
import java.util.Vector;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.apache.log4j.Decoder;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.apache.log4j.UtilLoggingLevel;
import org.apache.log4j.spi.LocationInfo;
import org.apache.log4j.spi.LoggingEvent;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
/**
* Decodes Logging Events in XML formated into elements that are used by
* Chainsaw.
*
* NOTE: Only a single LoggingEvent is returned from the decode method
* even though the DTD supports multiple events nested in an eventSet.
*
* @author Scott Deboy <[EMAIL PROTECTED]>
* @author Paul Smith <[EMAIL PROTECTED]>
*
*/
public class XMLDecoder implements Decoder {
private static final String BEGINPART =
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?><!DOCTYPE log4j:eventSet SYSTEM
\"log4j.dtd\"><log4j:eventSet version=\"1.2\"
xmlns:log4j=\"http://jakarta.apache.org/log4j/\">";
private static final String ENDPART = "</log4j:eventSet>";
private static final String RECORD_END = "</log4j:event>";
private StringBuffer buf = new StringBuffer();
private DocumentBuilderFactory dbf;
private DocumentBuilder docBuilder;
private Map additionalProperties = Collections.EMPTY_MAP;
private String partialEvent;
public XMLDecoder() {
dbf = DocumentBuilderFactory.newInstance();
dbf.setValidating(false);
try {
docBuilder = dbf.newDocumentBuilder();
docBuilder.setErrorHandler(new SAXErrorHandler());
docBuilder.setEntityResolver(new Log4jEntityResolver());
} catch (ParserConfigurationException pce) {
System.err.println("Unable to get document builder");
}
}
/**
* Sets an additionalProperty map, where each Key/Value pair is
* automatically added to each LoggingEvent as it is decoded.
*
* This is useful, say, to include the source file name of the Logging events
* @param additionalProperties
*/
public void setAdditionalProperties(Map additionalProperties) {
this.additionalProperties = additionalProperties;
}
/**
* Converts the LoggingEvent data in XML string format into an actual
* XML Document class instance.
* @param data
* @return
*/
private Document parse(String data) {
if (docBuilder == null) {
return null;
}
Document document = null;
try {
// we change the system ID to a valid URI so that Crimson won't
// 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
* on some JDK 1.4 impls, there's a known Bug that causes a memory leak
*/
buf = new StringBuffer(1024);
buf.append(BEGINPART);
buf.append(data);
buf.append(ENDPART);
InputSource inputSource =
new InputSource(new StringReader(buf.toString()));
inputSource.setSystemId("dummy://log4j.dtd");
document = docBuilder.parse(inputSource);
} catch (Exception e) {
e.printStackTrace();
}
return document;
}
/**
* Reads the contents of the file into a String
* @param file the file to load
* @return The contents of the file as a String
* @throws IOException if an error occurred during the loading process
*/
private String loadFileSource(File file) throws IOException {
LineNumberReader reader = null;
StringBuffer buf = new StringBuffer(1024);
try {
reader = new LineNumberReader(new FileReader(file));
String line = null;
while ((line = reader.readLine()) != null) {
buf.append(line);
}
} catch (IOException e) {
throw e;
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (Exception e) {
}
}
return buf.toString();
}
/**
* Decodes a File into a Vector of LoggingEvents
* @param file the file to decode events from
* @return Vector of LoggingEvents
* @throws IOException
*/
public Vector decode(File file) throws IOException {
String fileContents = loadFileSource(file);
Document doc = parse(fileContents);
if (doc == null) {
return null;
}
return decodeEvents(fileContents);
}
public Vector decodeEvents(String document) {
if (document != null) {
document = document.trim();
if (document.equals("")) {
return null;
} else {
String newDoc=null;
String newPartialEvent=null;
//separate the string into the last portion ending with </log4j:event>
(which will
//be processed) and the partial event which will be combined and
processed in the next section
if (document.lastIndexOf(RECORD_END) + RECORD_END.length() <
document.length()) {
newDoc = document.substring(0, document.lastIndexOf(RECORD_END) +
RECORD_END.length());
newPartialEvent =
document.substring(document.lastIndexOf(RECORD_END) + RECORD_END.length());
} else {
newDoc = document;
}
if (partialEvent != null) {
newDoc=partialEvent + newDoc;
}
partialEvent=newPartialEvent;
Document doc = parse(newDoc);
if (doc == null) {
return null;
}
return decodeEvents(doc);
}
}
return null;
}
/**
* Converts the string data into an XML Document, and then soaks out the
* relevant bits to form a new LoggingEvent instance which can be used
* by any Log4j element locally.
* @param data
* @return a single LoggingEvent
*/
public LoggingEvent decode(String data) {
Document document = parse(data);
if (document == null) {
return null;
}
Vector events = decodeEvents(document);
if (events.size() > 0) {
return (LoggingEvent) events.firstElement();
}
return null;
}
/**
* Given a Document, converts the XML into a Vector of LoggingEvents
* @param document
* @return
*/
private Vector decodeEvents(Document document) {
Vector events = new Vector();
Logger logger = null;
long timeStamp = 0L;
String level = null;
String threadName = null;
Object message = null;
String ndc = null;
Hashtable mdc = null;
String[] exception = null;
String className = null;
String methodName = null;
String fileName = null;
String lineNumber = null;
Hashtable properties = null;
NodeList nl = document.getElementsByTagName("log4j:eventSet");
Node eventSet = nl.item(0);
NodeList eventList = eventSet.getChildNodes();
for (int eventIndex = 0; eventIndex < eventList.getLength();
eventIndex++) {
Node eventNode = eventList.item(eventIndex);
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();
NodeList list = eventNode.getChildNodes();
int listLength = list.getLength();
for (int y = 0; y < listLength; y++) {
String tagName = list.item(y).getNodeName();
if (tagName.equalsIgnoreCase("log4j:message")) {
message = getCData(list.item(y));
}
if (tagName.equalsIgnoreCase("log4j:NDC")) {
ndc = getCData(list.item(y));
}
if (tagName.equalsIgnoreCase("log4j:MDC")) {
mdc = new Hashtable();
NodeList propertyList = list.item(y).getChildNodes();
int propertyLength = propertyList.getLength();
for (int i = 0; i < propertyLength; i++) {
String propertyTag = propertyList.item(i).getNodeName();
if (propertyTag.equalsIgnoreCase("log4j:data")) {
Node property = propertyList.item(i);
String name =
property.getAttributes().getNamedItem("name").getNodeValue();
String value =
property.getAttributes().getNamedItem("value").getNodeValue();
mdc.put(name, value);
}
}
}
if (tagName.equalsIgnoreCase("log4j:throwable")) {
exception = new String[] { getCData(list.item(y)) };
}
if (tagName.equalsIgnoreCase("log4j:locationinfo")) {
className =
list.item(y).getAttributes().getNamedItem("class").getNodeValue();
methodName =
list.item(y).getAttributes().getNamedItem("method").getNodeValue();
fileName =
list.item(y).getAttributes().getNamedItem("file").getNodeValue();
lineNumber =
list.item(y).getAttributes().getNamedItem("line").getNodeValue();
}
if (tagName.equalsIgnoreCase("log4j:properties")) {
properties = new Hashtable();
NodeList propertyList = list.item(y).getChildNodes();
int propertyLength = propertyList.getLength();
for (int i = 0; i < propertyLength; i++) {
String propertyTag = propertyList.item(i).getNodeName();
if (propertyTag.equalsIgnoreCase("log4j:data")) {
Node property = propertyList.item(i);
String name =
property.getAttributes().getNamedItem("name").getNodeValue();
String value =
property.getAttributes().getNamedItem("value").getNodeValue();
properties.put(name, value);
}
}
}
/**
* We add all the additional properties to the properties
* hashtable
*/
if (additionalProperties.size() > 0) {
if (properties == null) {
properties = new Hashtable(additionalProperties);
} else {
properties.putAll(additionalProperties);
}
}
}
Level levelImpl = null;
if ((properties != null) && (properties.get("log4j.eventtype") != null)) {
String s = (String)properties.get("log4j.eventtype");
if (s.equalsIgnoreCase("util-logging")) {
levelImpl=UtilLoggingLevel.toLevel(level);
}
}
if (levelImpl==null) {
levelImpl=Level.toLevel(level);
}
events.add(
new LoggingEvent(
logger.getName(), logger, timeStamp, levelImpl, threadName, message, ndc,
mdc, exception,
new LocationInfo(fileName, className, methodName, lineNumber),
properties));
}
return events;
}
private String getCData(Node n) {
StringBuffer buf = new StringBuffer();
NodeList nl = n.getChildNodes();
for (int x = 0; x < nl.getLength(); x++) {
Node innerNode = nl.item(x);
if (
(innerNode.getNodeType() == Node.TEXT_NODE)
|| (innerNode.getNodeType() == Node.CDATA_SECTION_NODE)) {
buf.append(innerNode.getNodeValue());
}
}
return buf.toString();
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]