1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.log4j.chainsaw;
18
19 import java.text.DateFormat;
20 import java.util.ArrayList;
21 import java.util.Comparator;
22 import java.util.Date;
23 import java.util.Iterator;
24 import java.util.List;
25 import java.util.SortedSet;
26 import java.util.TreeSet;
27 import javax.swing.table.AbstractTableModel;
28 import org.apache.log4j.Priority;
29 import org.apache.log4j.Logger;
30
31
32
33
34
35
36
37 class MyTableModel
38 extends AbstractTableModel
39 {
40
41
42 private static final Logger LOG = Logger.getLogger(MyTableModel.class);
43
44
45 private static final Comparator MY_COMP = new Comparator()
46 {
47
48 public int compare(Object aObj1, Object aObj2) {
49 if ((aObj1 == null) && (aObj2 == null)) {
50 return 0;
51 } else if (aObj1 == null) {
52 return -1;
53 } else if (aObj2 == null) {
54 return 1;
55 }
56
57
58 final EventDetails le1 = (EventDetails) aObj1;
59 final EventDetails le2 = (EventDetails) aObj2;
60
61 if (le1.getTimeStamp() < le2.getTimeStamp()) {
62 return 1;
63 }
64
65 return -1;
66 }
67 };
68
69
70
71
72
73 private class Processor
74 implements Runnable
75 {
76
77 public void run() {
78 while (true) {
79 try {
80 Thread.sleep(1000);
81 } catch (InterruptedException e) {
82
83 }
84
85 synchronized (mLock) {
86 if (mPaused) {
87 continue;
88 }
89
90 boolean toHead = true;
91 boolean needUpdate = false;
92 final Iterator it = mPendingEvents.iterator();
93 while (it.hasNext()) {
94 final EventDetails event = (EventDetails) it.next();
95 mAllEvents.add(event);
96 toHead = toHead && (event == mAllEvents.first());
97 needUpdate = needUpdate || matchFilter(event);
98 }
99 mPendingEvents.clear();
100
101 if (needUpdate) {
102 updateFilteredEvents(toHead);
103 }
104 }
105 }
106
107 }
108 }
109
110
111
112 private static final String[] COL_NAMES = {
113 "Time", "Priority", "Trace", "Category", "NDC", "Message"};
114
115
116 private static final EventDetails[] EMPTY_LIST = new EventDetails[] {};
117
118
119 private static final DateFormat DATE_FORMATTER =
120 DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM);
121
122
123 private final Object mLock = new Object();
124
125 private final SortedSet mAllEvents = new TreeSet(MY_COMP);
126
127 private EventDetails[] mFilteredEvents = EMPTY_LIST;
128
129 private final List mPendingEvents = new ArrayList();
130
131 private boolean mPaused = false;
132
133
134 private String mThreadFilter = "";
135
136 private String mMessageFilter = "";
137
138 private String mNDCFilter = "";
139
140 private String mCategoryFilter = "";
141
142 private Priority mPriorityFilter = Priority.DEBUG;
143
144
145
146
147
148
149 MyTableModel() {
150 final Thread t = new Thread(new Processor());
151 t.setDaemon(true);
152 t.start();
153 }
154
155
156
157
158
159
160
161 public int getRowCount() {
162 synchronized (mLock) {
163 return mFilteredEvents.length;
164 }
165 }
166
167
168 public int getColumnCount() {
169
170 return COL_NAMES.length;
171 }
172
173
174 public String getColumnName(int aCol) {
175
176 return COL_NAMES[aCol];
177 }
178
179
180 public Class getColumnClass(int aCol) {
181
182 return (aCol == 2) ? Boolean.class : Object.class;
183 }
184
185
186 public Object getValueAt(int aRow, int aCol) {
187 synchronized (mLock) {
188 final EventDetails event = mFilteredEvents[aRow];
189
190 if (aCol == 0) {
191 return DATE_FORMATTER.format(new Date(event.getTimeStamp()));
192 } else if (aCol == 1) {
193 return event.getPriority();
194 } else if (aCol == 2) {
195 return (event.getThrowableStrRep() == null)
196 ? Boolean.FALSE : Boolean.TRUE;
197 } else if (aCol == 3) {
198 return event.getCategoryName();
199 } else if (aCol == 4) {
200 return event.getNDC();
201 }
202 return event.getMessage();
203 }
204 }
205
206
207
208
209
210
211
212
213
214
215
216 public void setPriorityFilter(Priority aPriority) {
217 synchronized (mLock) {
218 mPriorityFilter = aPriority;
219 updateFilteredEvents(false);
220 }
221 }
222
223
224
225
226
227
228 public void setThreadFilter(String aStr) {
229 synchronized (mLock) {
230 mThreadFilter = aStr.trim();
231 updateFilteredEvents(false);
232 }
233 }
234
235
236
237
238
239
240 public void setMessageFilter(String aStr) {
241 synchronized (mLock) {
242 mMessageFilter = aStr.trim();
243 updateFilteredEvents(false);
244 }
245 }
246
247
248
249
250
251
252 public void setNDCFilter(String aStr) {
253 synchronized (mLock) {
254 mNDCFilter = aStr.trim();
255 updateFilteredEvents(false);
256 }
257 }
258
259
260
261
262
263
264 public void setCategoryFilter(String aStr) {
265 synchronized (mLock) {
266 mCategoryFilter = aStr.trim();
267 updateFilteredEvents(false);
268 }
269 }
270
271
272
273
274
275
276 public void addEvent(EventDetails aEvent) {
277 synchronized (mLock) {
278 mPendingEvents.add(aEvent);
279 }
280 }
281
282
283
284
285 public void clear() {
286 synchronized (mLock) {
287 mAllEvents.clear();
288 mFilteredEvents = new EventDetails[0];
289 mPendingEvents.clear();
290 fireTableDataChanged();
291 }
292 }
293
294
295 public void toggle() {
296 synchronized (mLock) {
297 mPaused = !mPaused;
298 }
299 }
300
301
302 public boolean isPaused() {
303 synchronized (mLock) {
304 return mPaused;
305 }
306 }
307
308
309
310
311
312
313
314 public EventDetails getEventDetails(int aRow) {
315 synchronized (mLock) {
316 return mFilteredEvents[aRow];
317 }
318 }
319
320
321
322
323
324
325
326
327
328
329
330 private void updateFilteredEvents(boolean aInsertedToFront) {
331 final long start = System.currentTimeMillis();
332 final List filtered = new ArrayList();
333 final int size = mAllEvents.size();
334 final Iterator it = mAllEvents.iterator();
335
336 while (it.hasNext()) {
337 final EventDetails event = (EventDetails) it.next();
338 if (matchFilter(event)) {
339 filtered.add(event);
340 }
341 }
342
343 final EventDetails lastFirst = (mFilteredEvents.length == 0)
344 ? null
345 : mFilteredEvents[0];
346 mFilteredEvents = (EventDetails[]) filtered.toArray(EMPTY_LIST);
347
348 if (aInsertedToFront && (lastFirst != null)) {
349 final int index = filtered.indexOf(lastFirst);
350 if (index < 1) {
351 LOG.warn("In strange state");
352 fireTableDataChanged();
353 } else {
354 fireTableRowsInserted(0, index - 1);
355 }
356 } else {
357 fireTableDataChanged();
358 }
359
360 final long end = System.currentTimeMillis();
361 LOG.debug("Total time [ms]: " + (end - start)
362 + " in update, size: " + size);
363 }
364
365
366
367
368
369
370
371 private boolean matchFilter(EventDetails aEvent) {
372 if (aEvent.getPriority().isGreaterOrEqual(mPriorityFilter) &&
373 (aEvent.getThreadName().indexOf(mThreadFilter) >= 0) &&
374 (aEvent.getCategoryName().indexOf(mCategoryFilter) >= 0) &&
375 ((mNDCFilter.length() == 0) ||
376 ((aEvent.getNDC() != null) &&
377 (aEvent.getNDC().indexOf(mNDCFilter) >= 0))))
378 {
379 final String rm = aEvent.getMessage();
380 if (rm == null) {
381
382 return (mMessageFilter.length() == 0);
383 } else {
384 return (rm.indexOf(mMessageFilter) >= 0);
385 }
386 }
387
388 return false;
389 }
390 }