001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.log4j.chainsaw; 018 019import java.util.StringTokenizer; 020import org.apache.log4j.Level; 021import org.xml.sax.Attributes; 022import org.xml.sax.SAXException; 023import org.xml.sax.helpers.DefaultHandler; 024 025/** 026 * A content handler for document containing Log4J events logged using the 027 * XMLLayout class. It will create events and add them to a supplied model. 028 * 029 * @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a> 030 * @version 1.0 031 */ 032class XMLFileHandler 033 extends DefaultHandler 034{ 035 /** represents the event tag **/ 036 private static final String TAG_EVENT = "log4j:event"; 037 /** represents the message tag **/ 038 private static final String TAG_MESSAGE = "log4j:message"; 039 /** represents the ndc tag **/ 040 private static final String TAG_NDC = "log4j:NDC"; 041 /** represents the throwable tag **/ 042 private static final String TAG_THROWABLE = "log4j:throwable"; 043 /** represents the location info tag **/ 044 private static final String TAG_LOCATION_INFO = "log4j:locationInfo"; 045 046 /** where to put the events **/ 047 private final MyTableModel mModel; 048 /** the number of events in the document **/ 049 private int mNumEvents; 050 051 /** the time of the event **/ 052 private long mTimeStamp; 053 /** the priority (level) of the event **/ 054 private Level mLevel; 055 /** the category of the event **/ 056 private String mCategoryName; 057 /** the NDC for the event **/ 058 private String mNDC; 059 /** the thread for the event **/ 060 private String mThreadName; 061 /** the msg for the event **/ 062 private String mMessage; 063 /** the throwable details the event **/ 064 private String[] mThrowableStrRep; 065 /** the location details for the event **/ 066 private String mLocationDetails; 067 /** buffer for collecting text **/ 068 private final StringBuffer mBuf = new StringBuffer(); 069 070 /** 071 * Creates a new <code>XMLFileHandler</code> instance. 072 * 073 * @param aModel where to add the events 074 */ 075 XMLFileHandler(MyTableModel aModel) { 076 mModel = aModel; 077 } 078 079 /** @see DefaultHandler **/ 080 public void startDocument() 081 throws SAXException 082 { 083 mNumEvents = 0; 084 } 085 086 /** @see DefaultHandler **/ 087 public void characters(char[] aChars, int aStart, int aLength) { 088 mBuf.append(String.valueOf(aChars, aStart, aLength)); 089 } 090 091 /** @see DefaultHandler **/ 092 public void endElement(String aNamespaceURI, 093 String aLocalName, 094 String aQName) 095 { 096 if (TAG_EVENT.equals(aQName)) { 097 addEvent(); 098 resetData(); 099 } else if (TAG_NDC.equals(aQName)) { 100 mNDC = mBuf.toString(); 101 } else if (TAG_MESSAGE.equals(aQName)) { 102 mMessage = mBuf.toString(); 103 } else if (TAG_THROWABLE.equals(aQName)) { 104 final StringTokenizer st = 105 new StringTokenizer(mBuf.toString(), "\n\t"); 106 mThrowableStrRep = new String[st.countTokens()]; 107 if (mThrowableStrRep.length > 0) { 108 mThrowableStrRep[0] = st.nextToken(); 109 for (int i = 1; i < mThrowableStrRep.length; i++) { 110 mThrowableStrRep[i] = "\t" + st.nextToken(); 111 } 112 } 113 } 114 } 115 116 /** @see DefaultHandler **/ 117 public void startElement(String aNamespaceURI, 118 String aLocalName, 119 String aQName, 120 Attributes aAtts) 121 { 122 mBuf.setLength(0); 123 124 if (TAG_EVENT.equals(aQName)) { 125 mThreadName = aAtts.getValue("thread"); 126 mTimeStamp = Long.parseLong(aAtts.getValue("timestamp")); 127 mCategoryName = aAtts.getValue("logger"); 128 mLevel = Level.toLevel(aAtts.getValue("level")); 129 } else if (TAG_LOCATION_INFO.equals(aQName)) { 130 mLocationDetails = aAtts.getValue("class") + "." 131 + aAtts.getValue("method") 132 + "(" + aAtts.getValue("file") + ":" + aAtts.getValue("line") 133 + ")"; 134 } 135 } 136 137 /** @return the number of events in the document **/ 138 int getNumEvents() { 139 return mNumEvents; 140 } 141 142 //////////////////////////////////////////////////////////////////////////// 143 // Private methods 144 //////////////////////////////////////////////////////////////////////////// 145 146 /** Add an event to the model **/ 147 private void addEvent() { 148 mModel.addEvent(new EventDetails(mTimeStamp, 149 mLevel, 150 mCategoryName, 151 mNDC, 152 mThreadName, 153 mMessage, 154 mThrowableStrRep, 155 mLocationDetails)); 156 mNumEvents++; 157 } 158 159 /** Reset the data for an event **/ 160 private void resetData() { 161 mTimeStamp = 0; 162 mLevel = null; 163 mCategoryName = null; 164 mNDC = null; 165 mThreadName = null; 166 mMessage = null; 167 mThrowableStrRep = null; 168 mLocationDetails = null; 169 } 170}