View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.log4j.chainsaw;
18  
19  import java.util.StringTokenizer;
20  import org.apache.log4j.Level;
21  import org.xml.sax.Attributes;
22  import org.xml.sax.SAXException;
23  import org.xml.sax.helpers.DefaultHandler;
24  
25  /**
26   * A content handler for document containing Log4J events logged using the
27   * XMLLayout class. It will create events and add them to a supplied model.
28   *
29   * @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a>
30   * @version 1.0
31   */
32  class XMLFileHandler
33      extends DefaultHandler
34  {
35      /** represents the event tag **/
36      private static final String TAG_EVENT = "log4j:event";
37      /** represents the message tag **/
38      private static final String TAG_MESSAGE = "log4j:message";
39      /** represents the ndc tag **/
40      private static final String TAG_NDC = "log4j:NDC";
41      /** represents the throwable tag **/
42      private static final String TAG_THROWABLE = "log4j:throwable";
43      /** represents the location info tag **/
44      private static final String TAG_LOCATION_INFO = "log4j:locationInfo";
45  
46      /** where to put the events **/
47      private final MyTableModel mModel;
48      /** the number of events in the document **/
49      private int mNumEvents;
50  
51      /** the time of the event **/
52      private long mTimeStamp;
53      /** the priority (level) of the event **/
54      private Level mLevel;
55      /** the category of the event **/
56      private String mCategoryName;
57      /** the NDC for the event **/
58      private String mNDC;
59      /** the thread for the event **/
60      private String mThreadName;
61      /** the msg for the event **/
62      private String mMessage;
63      /** the throwable details the event **/
64      private String[] mThrowableStrRep;
65      /** the location details for the event **/
66      private String mLocationDetails;
67      /** buffer for collecting text **/
68      private final StringBuffer mBuf = new StringBuffer();
69  
70      /**
71       * Creates a new <code>XMLFileHandler</code> instance.
72       *
73       * @param aModel where to add the events
74       */
75      XMLFileHandler(MyTableModel aModel) {
76          mModel = aModel;
77      }
78  
79      /** @see DefaultHandler **/
80      public void startDocument()
81          throws SAXException
82      {
83          mNumEvents = 0;
84      }
85  
86      /** @see DefaultHandler **/
87      public void characters(char[] aChars, int aStart, int aLength) {
88          mBuf.append(String.valueOf(aChars, aStart, aLength));
89      }
90  
91      /** @see DefaultHandler **/
92      public void endElement(String aNamespaceURI,
93                             String aLocalName,
94                             String aQName)
95      {
96          if (TAG_EVENT.equals(aQName)) {
97              addEvent();
98              resetData();
99          } 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 }