1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.log4j.chainsaw;
19
20 import org.apache.log4j.LogManager;
21 import org.apache.log4j.Logger;
22 import org.apache.log4j.chainsaw.color.RuleColorizer;
23 import org.apache.log4j.chainsaw.helper.SwingHelper;
24 import org.apache.log4j.helpers.Constants;
25 import org.apache.log4j.rule.Rule;
26 import org.apache.log4j.spi.LocationInfo;
27 import org.apache.log4j.spi.LoggingEvent;
28
29 import javax.swing.*;
30 import javax.swing.event.EventListenerList;
31 import javax.swing.table.AbstractTableModel;
32 import java.beans.PropertyChangeEvent;
33 import java.beans.PropertyChangeListener;
34 import java.beans.PropertyChangeSupport;
35 import java.util.*;
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 class ChainsawCyclicBufferTableModel extends AbstractTableModel
52 implements EventContainer, PropertyChangeListener {
53
54 private static final int DEFAULT_CAPACITY = 5000;
55
56 private boolean cyclic = true;
57 private int cyclicBufferSize;
58
59 List unfilteredList;
60
61 List filteredList;
62 private boolean currentSortAscending;
63 private int currentSortColumn;
64 private final EventListenerList eventListenerList = new EventListenerList();
65 private final List<String> columnNames = new ArrayList<>(ChainsawColumns.getColumnsNames());
66 private boolean sortEnabled = false;
67 private boolean reachedCapacity = false;
68 private final Logger logger = LogManager.getLogger(ChainsawCyclicBufferTableModel.class);
69
70
71 private final LoggerNameModel loggerNameModelDelegate = new LoggerNameModelSupport();
72 private final Object mutex = new Object();
73
74
75
76 int uniqueRow;
77 private final Set uniquePropertyKeys = new HashSet();
78 private Rule ruleMediator;
79 private final PropertyChangeSupport propertySupport = new PropertyChangeSupport(this);
80 private RuleColorizer colorizer;
81 private final String tableModelName;
82
83 public ChainsawCyclicBufferTableModel(int cyclicBufferSize, RuleColorizer colorizer, String tableModelName) {
84 propertySupport.addPropertyChangeListener("cyclic", new ModelChanger());
85 this.cyclicBufferSize = cyclicBufferSize;
86 this.colorizer = colorizer;
87 this.tableModelName = tableModelName;
88
89 unfilteredList = new CyclicBufferList(cyclicBufferSize);
90 filteredList = new CyclicBufferList(cyclicBufferSize);
91 }
92
93
94
95
96 public void propertyChange(PropertyChangeEvent evt) {
97 if (evt.getSource() instanceof Rule) {
98 if (evt.getSource() == ruleMediator && evt.getPropertyName().equals("findRule")) {
99 if (((RuleMediator) evt.getSource()).isFindRuleRequired()) {
100
101 reFilter();
102 }
103 } else {
104 reFilter();
105 }
106 }
107 }
108
109 public List<LoggingEventWrapper> getMatchingEvents(Rule rule) {
110 List<LoggingEventWrapper> list = new ArrayList<>();
111 List unfilteredCopy;
112 synchronized (mutex) {
113 unfilteredCopy = new ArrayList(unfilteredList);
114 }
115
116 for (Object anUnfilteredCopy : unfilteredCopy) {
117 LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) anUnfilteredCopy;
118
119 if (rule.evaluate(loggingEventWrapper.getLoggingEvent(), null)) {
120 list.add(loggingEventWrapper);
121 }
122 }
123
124 return list;
125 }
126
127 public void reFilter() {
128 final int previousSize;
129 final int newSize;
130 synchronized (mutex) {
131
132 propertySupport.firePropertyChange("refilter", Boolean.FALSE, Boolean.TRUE);
133 previousSize = filteredList.size();
134 filteredList.clear();
135 if (ruleMediator == null) {
136 LoggingEventWrapper lastEvent = null;
137 for (Object anUnfilteredList : unfilteredList) {
138 LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) anUnfilteredList;
139 loggingEventWrapper.setDisplayed(true);
140 updateEventMillisDelta(loggingEventWrapper, lastEvent);
141 filteredList.add(loggingEventWrapper);
142 lastEvent = loggingEventWrapper;
143 }
144 } else {
145 Iterator iter = unfilteredList.iterator();
146 LoggingEventWrapper lastEvent = null;
147 while (iter.hasNext()) {
148 LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) iter.next();
149
150 if (ruleMediator.evaluate(loggingEventWrapper.getLoggingEvent(), null)) {
151 loggingEventWrapper.setDisplayed(true);
152 filteredList.add(loggingEventWrapper);
153 updateEventMillisDelta(loggingEventWrapper, lastEvent);
154 lastEvent = loggingEventWrapper;
155 } else {
156 loggingEventWrapper.setDisplayed(false);
157 }
158 }
159 }
160 newSize = filteredList.size();
161 }
162 SwingHelper.invokeOnEDT(() -> {
163 if (newSize > 0) {
164 if (previousSize == newSize) {
165
166 fireTableRowsUpdated(0, newSize - 1);
167 } else if (previousSize > newSize) {
168
169 fireTableRowsUpdated(0, newSize - 1);
170
171 fireTableDataChanged();
172 } else if (previousSize < newSize) {
173
174 if (previousSize > 0) {
175 fireTableRowsUpdated(0, previousSize - 1);
176 }
177 fireTableRowsInserted(Math.max(0, previousSize), newSize - 1);
178 }
179 } else {
180
181 fireTableDataChanged();
182 }
183 notifyCountListeners();
184
185 SwingHelper.invokeOnEDT(() -> propertySupport.firePropertyChange("refilter", Boolean.TRUE, Boolean.FALSE));
186 });
187 }
188
189 public int locate(Rule rule, int startLocation, boolean searchForward) {
190 List filteredListCopy;
191 synchronized (mutex) {
192 filteredListCopy = new ArrayList(filteredList);
193 }
194 if (searchForward) {
195 for (int i = startLocation; i < filteredListCopy.size(); i++) {
196 if (rule.evaluate(((LoggingEventWrapper) filteredListCopy.get(i)).getLoggingEvent(), null)) {
197 return i;
198 }
199 }
200
201 for (int i = 0; i < startLocation; i++) {
202 if (rule.evaluate(((LoggingEventWrapper) filteredListCopy.get(i)).getLoggingEvent(), null)) {
203 return i;
204 }
205 }
206 } else {
207 for (int i = startLocation; i > -1; i--) {
208 if (rule.evaluate(((LoggingEventWrapper) filteredListCopy.get(i)).getLoggingEvent(), null)) {
209 return i;
210 }
211 }
212
213 for (int i = filteredListCopy.size() - 1; i > startLocation; i--) {
214 if (rule.evaluate(((LoggingEventWrapper) filteredListCopy.get(i)).getLoggingEvent(), null)) {
215 return i;
216 }
217 }
218 }
219
220 return -1;
221 }
222
223
224
225
226 public void removeLoggerNameListener(LoggerNameListener l) {
227 loggerNameModelDelegate.removeLoggerNameListener(l);
228 }
229
230
231
232
233
234 public boolean addLoggerName(String loggerName) {
235 return loggerNameModelDelegate.addLoggerName(loggerName);
236 }
237
238 public String toString() {
239 return "ChainsawCyclicBufferTableModel{" +
240 "name='" + tableModelName + '\'' +
241 '}';
242 }
243
244 public void reset() {
245 loggerNameModelDelegate.reset();
246 }
247
248
249
250
251 public void addLoggerNameListener(LoggerNameListener l) {
252 loggerNameModelDelegate.addLoggerNameListener(l);
253 }
254
255
256
257
258 public Collection getLoggerNames() {
259 return loggerNameModelDelegate.getLoggerNames();
260 }
261
262 public void addEventCountListener(EventCountListener listener) {
263 eventListenerList.add(EventCountListener.class, listener);
264 }
265
266 public boolean isSortable(int col) {
267 return true;
268 }
269
270 public void notifyCountListeners() {
271 EventCountListener[] listeners = eventListenerList.getListeners(EventCountListener.class);
272
273 int filteredListSize;
274 int unfilteredListSize;
275 synchronized (mutex) {
276 filteredListSize = filteredList.size();
277 unfilteredListSize = unfilteredList.size();
278 }
279 for (EventCountListener listener : listeners) {
280 listener.eventCountChanged(
281 filteredListSize, unfilteredListSize);
282 }
283 }
284
285
286
287
288
289
290
291
292 public void setRuleMediator(RuleMediator ruleMediator) {
293 if (this.ruleMediator != null) {
294 this.ruleMediator.removePropertyChangeListener(this);
295 }
296
297 this.ruleMediator = ruleMediator;
298
299 if (this.ruleMediator != null) {
300 this.ruleMediator.addPropertyChangeListener(this);
301 }
302 reFilter();
303 }
304
305
306
307
308 public void sort() {
309 boolean sort;
310 final int filteredListSize;
311 synchronized (mutex) {
312 filteredListSize = filteredList.size();
313 sort = (sortEnabled && filteredListSize > 0);
314 if (sort) {
315
316 LoggingEventWrapper lastEvent = null;
317 for (Object aFilteredList : filteredList) {
318 LoggingEventWrapper e = (LoggingEventWrapper) aFilteredList;
319 e.setDisplayed(true);
320 updateEventMillisDelta(e, lastEvent);
321 lastEvent = e;
322 }
323 filteredList.sort(new ColumnComparator(
324 getColumnName(currentSortColumn), currentSortColumn,
325 currentSortAscending));
326 }
327 }
328 if (sort) {
329 SwingHelper.invokeOnEDT(() -> fireTableRowsUpdated(0, Math.max(filteredListSize - 1, 0)));
330 }
331 }
332
333 public boolean isSortEnabled() {
334 return sortEnabled;
335 }
336
337 public void sortColumn(int col, boolean ascending) {
338 logger.debug("request to sort col=" + col);
339 currentSortAscending = ascending;
340 currentSortColumn = col;
341 sortEnabled = true;
342 sort();
343 }
344
345
346
347
348 public void clearModel() {
349 reachedCapacity = false;
350
351 synchronized (mutex) {
352 unfilteredList.clear();
353 filteredList.clear();
354 uniqueRow = 0;
355 }
356
357 SwingHelper.invokeOnEDT(this::fireTableDataChanged);
358
359 notifyCountListeners();
360 loggerNameModelDelegate.reset();
361 }
362
363 public List getAllEvents() {
364 synchronized (mutex) {
365 return new ArrayList(unfilteredList);
366 }
367 }
368
369
370 public List getFilteredEvents() {
371
372 synchronized (mutex) {
373 return new ArrayList(filteredList);
374 }
375 }
376
377 public int getRowIndex(LoggingEventWrapper loggingEventWrapper) {
378 synchronized (mutex) {
379 return filteredList.indexOf(loggingEventWrapper);
380 }
381 }
382
383 public void removePropertyFromEvents(String propName) {
384
385 List filteredListCopy;
386 List unfilteredListCopy;
387 synchronized (mutex) {
388 filteredListCopy = new ArrayList(filteredList);
389 unfilteredListCopy = new ArrayList(unfilteredList);
390 }
391 for (int i = 0; i < filteredListCopy.size(); i++) {
392 LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) filteredListCopy.get(i);
393 Object result = loggingEventWrapper.removeProperty(propName);
394 if (result != null) {
395 fireRowUpdated(i, false);
396 }
397 }
398
399 for (Object anUnfilteredListCopy : unfilteredListCopy) {
400 LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) anUnfilteredListCopy;
401 loggingEventWrapper.removeProperty(propName);
402 }
403 }
404
405 public int updateEventsWithFindRule(Rule findRule) {
406 int count = 0;
407 List unfilteredListCopy;
408 synchronized (mutex) {
409 unfilteredListCopy = new ArrayList(unfilteredList);
410 }
411 for (Object anUnfilteredListCopy : unfilteredListCopy) {
412 LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) anUnfilteredListCopy;
413 loggingEventWrapper.evaluateSearchRule(findRule);
414
415 if (loggingEventWrapper.isSearchMatch() && loggingEventWrapper.isDisplayed()) {
416 count++;
417 }
418 }
419 return count;
420 }
421
422 public int findColoredRow(int startLocation, boolean searchForward) {
423 List filteredListCopy;
424 synchronized (mutex) {
425 filteredListCopy = new ArrayList(filteredList);
426 }
427 if (searchForward) {
428 for (int i = startLocation; i < filteredListCopy.size(); i++) {
429 LoggingEventWrapper event = (LoggingEventWrapper) filteredListCopy.get(i);
430 if (!event.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) ||
431 !event.getColorRuleForeground().equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND)) {
432 return i;
433 }
434 }
435
436 for (int i = 0; i < startLocation; i++) {
437 LoggingEventWrapper event = (LoggingEventWrapper) filteredListCopy.get(i);
438 if (!event.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) ||
439 !event.getColorRuleForeground().equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND)) {
440 return i;
441 }
442 }
443 } else {
444 for (int i = startLocation; i > -1; i--) {
445 LoggingEventWrapper event = (LoggingEventWrapper) filteredListCopy.get(i);
446 if (!event.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) ||
447 !event.getColorRuleForeground().equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND)) {
448 return i;
449 }
450 }
451
452 for (int i = filteredListCopy.size() - 1; i > startLocation; i--) {
453 LoggingEventWrapper event = (LoggingEventWrapper) filteredListCopy.get(i);
454 if (!event.getColorRuleBackground().equals(ChainsawConstants.COLOR_DEFAULT_BACKGROUND) ||
455 !event.getColorRuleForeground().equals(ChainsawConstants.COLOR_DEFAULT_FOREGROUND)) {
456 return i;
457 }
458 }
459 }
460
461 return -1;
462 }
463
464 public int getSearchMatchCount() {
465 int searchMatchCount = 0;
466 synchronized (mutex) {
467 for (Object aFilteredList : filteredList) {
468 LoggingEventWrapper wrapper = (LoggingEventWrapper) aFilteredList;
469 if (wrapper.isSearchMatch() && wrapper.isDisplayed()) {
470 searchMatchCount++;
471 }
472 }
473 }
474 return searchMatchCount;
475 }
476
477 public int getColumnCount() {
478 return columnNames.size();
479 }
480
481 public String getColumnName(int column) {
482 return columnNames.get(column);
483 }
484
485 public LoggingEventWrapper getRow(int row) {
486 synchronized (mutex) {
487 if (row < filteredList.size() && row > -1) {
488 return (LoggingEventWrapper) filteredList.get(row);
489 }
490 }
491
492 return null;
493 }
494
495 public int getRowCount() {
496 synchronized (mutex) {
497 return filteredList.size();
498 }
499 }
500
501 public Object getValueAt(int rowIndex, int columnIndex) {
502 LoggingEvent event = null;
503
504 synchronized (mutex) {
505 if (rowIndex < filteredList.size() && rowIndex > -1) {
506 event = ((LoggingEventWrapper) filteredList.get(rowIndex)).getLoggingEvent();
507 }
508 }
509
510 if (event == null) {
511 return null;
512 }
513
514 LocationInfo info = null;
515
516 if (event.locationInformationExists()) {
517 info = event.getLocationInformation();
518 }
519
520 switch (columnIndex + 1) {
521 case ChainsawColumns.INDEX_ID_COL_NAME:
522
523 Object id = event.getProperty(Constants.LOG4J_ID_KEY);
524
525 if (id != null) {
526 return id;
527 }
528
529 return rowIndex;
530
531 case ChainsawColumns.INDEX_LEVEL_COL_NAME:
532 return event.getLevel();
533
534 case ChainsawColumns.INDEX_LOG4J_MARKER_COL_NAME:
535 return event.getProperty(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE);
536
537 case ChainsawColumns.INDEX_MILLIS_DELTA_COL_NAME:
538 return event.getProperty(ChainsawConstants.MILLIS_DELTA_COL_NAME_LOWERCASE);
539
540 case ChainsawColumns.INDEX_LOGGER_COL_NAME:
541 return event.getLoggerName();
542
543 case ChainsawColumns.INDEX_TIMESTAMP_COL_NAME:
544 return new Date(event.getTimeStamp());
545
546 case ChainsawColumns.INDEX_MESSAGE_COL_NAME:
547 return event.getRenderedMessage();
548
549 case ChainsawColumns.INDEX_NDC_COL_NAME:
550 return event.getNDC();
551
552 case ChainsawColumns.INDEX_THREAD_COL_NAME:
553 return event.getThreadName();
554
555 case ChainsawColumns.INDEX_THROWABLE_COL_NAME:
556 return event.getThrowableStrRep();
557
558 case ChainsawColumns.INDEX_CLASS_COL_NAME:
559 return ((info == null) || ("?".equals(info.getClassName()))) ? "" : info.getClassName();
560
561 case ChainsawColumns.INDEX_FILE_COL_NAME:
562 return ((info == null) || ("?".equals(info.getFileName()))) ? "" : info.getFileName();
563
564 case ChainsawColumns.INDEX_LINE_COL_NAME:
565 return ((info == null) || ("?".equals(info.getLineNumber()))) ? "" : info.getLineNumber();
566
567 case ChainsawColumns.INDEX_METHOD_COL_NAME:
568 return ((info == null) || ("?".equals(info.getMethodName()))) ? "" : info.getMethodName();
569
570 default:
571
572 if (columnIndex < columnNames.size()) {
573
574 String result = event.getProperty(columnNames.get(columnIndex).toString());
575 if (result == null) {
576 String lowerColName = columnNames.get(columnIndex).toString().toLowerCase(Locale.ENGLISH);
577 Set<Map.Entry> entrySet = event.getProperties().entrySet();
578 for (Object anEntrySet : entrySet) {
579 Map.Entry thisEntry = (Map.Entry) anEntrySet;
580 if (thisEntry.getKey().toString().equalsIgnoreCase(lowerColName)) {
581 result = thisEntry.getValue().toString();
582 }
583 }
584 }
585 if (result != null) {
586 return result;
587 }
588 }
589 }
590 return "";
591 }
592
593 public boolean isAddRow(LoggingEventWrapper loggingEventWrapper) {
594 Object id = loggingEventWrapper.getLoggingEvent().getProperty(Constants.LOG4J_ID_KEY);
595
596
597 if (id == null) {
598 id = ++uniqueRow;
599 loggingEventWrapper.setProperty(Constants.LOG4J_ID_KEY, id.toString());
600 }
601
602 loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
603 Rule findRule = colorizer.getFindRule();
604 if (findRule != null) {
605 loggingEventWrapper.evaluateSearchRule(colorizer.getFindRule());
606 }
607
608 boolean rowAdded = false;
609
610
611
612
613
614
615
616 synchronized (mutex) {
617 if (cyclic) {
618 CyclicBufferList bufferList = (CyclicBufferList) unfilteredList;
619 if (bufferList.size() == bufferList.getMaxSize()) {
620 reachedCapacity = true;
621 }
622 }
623 int unfilteredSize = unfilteredList.size();
624 LoggingEventWrapper lastLoggingEventWrapper = null;
625 if (unfilteredSize > 0) {
626 lastLoggingEventWrapper = (LoggingEventWrapper) unfilteredList.get(unfilteredSize - 1);
627 }
628 unfilteredList.add(loggingEventWrapper);
629 if ((ruleMediator == null) || (ruleMediator.evaluate(loggingEventWrapper.getLoggingEvent(), null))) {
630 loggingEventWrapper.setDisplayed(true);
631 updateEventMillisDelta(loggingEventWrapper, lastLoggingEventWrapper);
632 filteredList.add(loggingEventWrapper);
633 rowAdded = true;
634 } else {
635 loggingEventWrapper.setDisplayed(false);
636 }
637 }
638
639 checkForNewColumn(loggingEventWrapper);
640
641 return rowAdded;
642 }
643
644 private void updateEventMillisDelta(LoggingEventWrapper loggingEventWrapper, LoggingEventWrapper lastLoggingEventWrapper) {
645 if (lastLoggingEventWrapper != null) {
646 loggingEventWrapper.setPreviousDisplayedEventTimestamp(lastLoggingEventWrapper.getLoggingEvent().getTimeStamp());
647 } else {
648
649 loggingEventWrapper.setPreviousDisplayedEventTimestamp(loggingEventWrapper.getLoggingEvent().getTimeStamp());
650 }
651 }
652
653 private void checkForNewColumn(LoggingEventWrapper loggingEventWrapper) {
654
655
656
657
658 boolean newColumn = uniquePropertyKeys.addAll(loggingEventWrapper.getPropertyKeySet());
659
660 if (newColumn) {
661
662
663
664 for (Object o : loggingEventWrapper.getPropertyKeySet()) {
665 String key = o.toString().toUpperCase();
666
667
668 if (!columnNames.contains(key) && !(Constants.LOG4J_ID_KEY.equalsIgnoreCase(key))) {
669 columnNames.add(key);
670 logger.debug("Adding col '" + key + "', columnNames=" + columnNames);
671 fireNewKeyColumnAdded(
672 new NewKeyEvent(
673 this, columnNames.indexOf(key), key, loggingEventWrapper.getLoggingEvent().getProperty(key)));
674 }
675 }
676 }
677 }
678
679 public void fireTableEvent(final int begin, final int end, final int count) {
680 SwingHelper.invokeOnEDT(() -> {
681 if (cyclic) {
682 if (!reachedCapacity) {
683
684 if ((begin + count) < cyclicBufferSize) {
685 fireTableRowsInserted(begin, end);
686 } else {
687
688
689 fireTableRowsInserted(begin, cyclicBufferSize - 1);
690 fireTableRowsUpdated(0, cyclicBufferSize - 1);
691 reachedCapacity = true;
692 }
693 } else {
694 fireTableRowsUpdated(0, cyclicBufferSize - 1);
695 }
696 } else {
697 fireTableRowsInserted(begin, end);
698 }
699 });
700 }
701
702 public void fireRowUpdated(int row, boolean checkForNewColumns) {
703 LoggingEventWrapper loggingEventWrapper = getRow(row);
704 if (loggingEventWrapper != null) {
705 loggingEventWrapper.updateColorRuleColors(colorizer.getBackgroundColor(loggingEventWrapper.getLoggingEvent()), colorizer.getForegroundColor(loggingEventWrapper.getLoggingEvent()));
706 Rule findRule = colorizer.getFindRule();
707 if (findRule != null) {
708 loggingEventWrapper.evaluateSearchRule(colorizer.getFindRule());
709 }
710
711 fireTableRowsUpdated(row, row);
712 if (checkForNewColumns) {
713
714 checkForNewColumn(loggingEventWrapper);
715 }
716 }
717 }
718
719
720
721
722 private void fireNewKeyColumnAdded(NewKeyEvent e) {
723 NewKeyListener[] listeners =
724 eventListenerList.getListeners(NewKeyListener.class);
725
726 for (NewKeyListener listener : listeners) {
727 listener.newKeyAdded(e);
728 }
729 }
730
731
732
733
734 public int getMaxSize() {
735 return cyclicBufferSize;
736 }
737
738
739
740
741 public void addNewKeyListener(NewKeyListener l) {
742 eventListenerList.add(NewKeyListener.class, l);
743 }
744
745
746
747
748 public void removeNewKeyListener(NewKeyListener l) {
749 eventListenerList.remove(NewKeyListener.class, l);
750 }
751
752
753
754
755 public boolean isCellEditable(int rowIndex, int columnIndex) {
756 if (getColumnName(columnIndex).equalsIgnoreCase(ChainsawConstants.LOG4J_MARKER_COL_NAME_LOWERCASE)) {
757 return true;
758 }
759
760 return columnIndex < columnNames.size() && super.isCellEditable(rowIndex, columnIndex);
761
762 }
763
764
765
766
767 public void setCyclic(final boolean cyclic) {
768 if (this.cyclic == cyclic) {
769 return;
770 }
771
772 final boolean old = this.cyclic;
773 this.cyclic = cyclic;
774 propertySupport.firePropertyChange("cyclic", old, cyclic);
775 }
776
777
778
779
780 public void addPropertyChangeListener(PropertyChangeListener l) {
781 propertySupport.addPropertyChangeListener(l);
782 }
783
784
785
786
787 public void addPropertyChangeListener(
788 String propertyName, PropertyChangeListener l) {
789 propertySupport.addPropertyChangeListener(propertyName, l);
790 }
791
792
793
794
795 public int size() {
796 synchronized (mutex) {
797 return unfilteredList.size();
798 }
799 }
800
801 private class ModelChanger implements PropertyChangeListener {
802
803
804
805 public void propertyChange(PropertyChangeEvent arg0) {
806 Thread thread =
807 new Thread(
808 () -> {
809 ProgressMonitor monitor = null;
810
811 int index = 0;
812
813 try {
814 synchronized (mutex) {
815 monitor =
816 new ProgressMonitor(
817 null, "Switching models...",
818 "Transferring between data structures, please wait...", 0,
819 unfilteredList.size() + 1);
820 monitor.setMillisToDecideToPopup(250);
821 monitor.setMillisToPopup(100);
822 logger.debug(
823 "Changing Model, isCyclic is now " + cyclic);
824
825 List newUnfilteredList;
826 List newFilteredList;
827
828 if (cyclic) {
829 newUnfilteredList = new CyclicBufferList(cyclicBufferSize);
830 newFilteredList = new CyclicBufferList(cyclicBufferSize);
831 } else {
832 newUnfilteredList = new ArrayList(cyclicBufferSize);
833 newFilteredList = new ArrayList(cyclicBufferSize);
834 }
835
836 int increment = 0;
837
838 for (Object anUnfilteredList : unfilteredList) {
839 LoggingEventWrapper loggingEventWrapper = (LoggingEventWrapper) anUnfilteredList;
840 newUnfilteredList.add(loggingEventWrapper);
841 monitor.setProgress(index++);
842 }
843
844 unfilteredList = newUnfilteredList;
845 filteredList = newFilteredList;
846 }
847
848 monitor.setNote("Refiltering...");
849 reFilter();
850
851 monitor.setProgress(index++);
852 } finally {
853 monitor.close();
854 }
855
856 logger.debug("Model Change completed");
857 });
858 thread.setPriority(Thread.MIN_PRIORITY + 1);
859 thread.start();
860 }
861 }
862 }