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.*;
21 import org.apache.log4j.chainsaw.color.RuleColorizer;
22 import org.apache.log4j.chainsaw.dnd.FileDnDTarget;
23 import org.apache.log4j.chainsaw.help.HelpManager;
24 import org.apache.log4j.chainsaw.help.Tutorial;
25 import org.apache.log4j.chainsaw.helper.SwingHelper;
26 import org.apache.log4j.chainsaw.icons.ChainsawIcons;
27 import org.apache.log4j.chainsaw.icons.LineIconFactory;
28 import org.apache.log4j.chainsaw.messages.MessageCenter;
29 import org.apache.log4j.chainsaw.osx.OSXIntegration;
30 import org.apache.log4j.chainsaw.plugins.PluginClassLoaderFactory;
31 import org.apache.log4j.chainsaw.prefs.*;
32 import org.apache.log4j.chainsaw.receivers.ReceiversHelper;
33 import org.apache.log4j.chainsaw.receivers.ReceiversPanel;
34 import org.apache.log4j.chainsaw.vfs.VFSLogFilePatternReceiver;
35 import org.apache.log4j.net.SocketNodeEventListener;
36 import org.apache.log4j.plugins.*;
37 import org.apache.log4j.rewrite.PropertyRewritePolicy;
38 import org.apache.log4j.rewrite.RewriteAppender;
39 import org.apache.log4j.rule.ExpressionRule;
40 import org.apache.log4j.rule.Rule;
41 import org.apache.log4j.spi.Decoder;
42 import org.apache.log4j.spi.LoggerRepository;
43 import org.apache.log4j.spi.LoggerRepositoryEx;
44 import org.apache.log4j.spi.LoggingEvent;
45 import org.apache.log4j.xml.DOMConfigurator;
46 import org.apache.log4j.xml.XMLDecoder;
47
48 import javax.swing.*;
49 import javax.swing.event.ChangeEvent;
50 import javax.swing.event.ChangeListener;
51 import javax.swing.event.EventListenerList;
52 import javax.swing.event.HyperlinkEvent;
53 import java.awt.*;
54 import java.awt.event.*;
55 import java.beans.PropertyChangeListener;
56 import java.io.File;
57 import java.io.IOException;
58 import java.lang.reflect.Method;
59 import java.net.MalformedURLException;
60 import java.net.URISyntaxException;
61 import java.net.URL;
62 import java.security.*;
63 import java.util.*;
64 import java.util.List;
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82 public class LogUI extends JFrame implements ChainsawViewer, SettingsListener {
83 private static final String MAIN_WINDOW_HEIGHT = "main.window.height";
84 private static final String MAIN_WINDOW_WIDTH = "main.window.width";
85 private static final String MAIN_WINDOW_Y = "main.window.y";
86 private static final String MAIN_WINDOW_X = "main.window.x";
87 private static ChainsawSplash splash;
88 private static final double DEFAULT_MAIN_RECEIVER_SPLIT_LOCATION = 0.85d;
89 private final JFrame preferencesFrame = new JFrame();
90 private boolean noReceiversDefined;
91 private ReceiversPanel receiversPanel;
92 private ChainsawTabbedPane tabbedPane;
93 private JToolBar toolbar;
94 private ChainsawStatusBar statusBar;
95 private ApplicationPreferenceModel applicationPreferenceModel;
96 private ApplicationPreferenceModelPanel applicationPreferenceModelPanel;
97 private final Map tableModelMap = new HashMap();
98 private final Map tableMap = new HashMap();
99 private final List<String> filterableColumns = new ArrayList<>();
100 private final Map<String, Component> panelMap = new HashMap<>();
101 ChainsawAppenderHandler handler;
102 private ChainsawToolBarAndMenus tbms;
103 private ChainsawAbout aboutBox;
104 private final SettingsManager sm = SettingsManager.getInstance();
105 private final JFrame tutorialFrame = new JFrame("Chainsaw Tutorial");
106 private JSplitPane mainReceiverSplitPane;
107 private double lastMainReceiverSplitLocation = DEFAULT_MAIN_RECEIVER_SPLIT_LOCATION;
108 private final List<LogPanel> identifierPanels = new ArrayList<>();
109 private int dividerSize;
110 private int cyclicBufferSize;
111 private static Logger logger;
112 private static String configurationURLAppArg;
113
114
115
116
117
118
119
120 private boolean isGUIFullyInitialized = false;
121 private final Object initializationLock = new Object();
122
123
124
125
126
127
128 private Action shutdownAction = null;
129
130
131
132
133
134 private EventListenerList shutdownListenerList = new EventListenerList();
135 private WelcomePanel welcomePanel;
136
137 private static final Object repositorySelectorGuard = new Object();
138 private static final LoggerRepositoryExImpl repositoryExImpl = new LoggerRepositoryExImpl(LogManager.getLoggerRepository());
139
140 private PluginRegistry pluginRegistry;
141
142 private Map<String, RuleColorizer> allColorizers = new HashMap<>();
143 private ReceiverConfigurationPanel receiverConfigurationPanel = new ReceiverConfigurationPanel();
144
145
146
147
148
149 public LogUI() {
150 super("Chainsaw");
151 setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
152
153 if (ChainsawIcons.WINDOW_ICON != null) {
154 setIconImage(new ImageIcon(ChainsawIcons.WINDOW_ICON).getImage());
155 }
156 }
157
158 private static final void showSplash(Frame owner) {
159 splash = new ChainsawSplash(owner);
160 SwingHelper.centerOnScreen(splash);
161 splash.setVisible(true);
162 }
163
164 private static final void removeSplash() {
165 if (splash != null) {
166 splash.setVisible(false);
167 splash.dispose();
168 }
169 }
170
171
172
173
174
175
176
177 public void addShutdownListener(ShutdownListener l) {
178 shutdownListenerList.add(ShutdownListener.class, l);
179 }
180
181
182
183
184
185
186
187 public void removeShutdownListener(ShutdownListener l) {
188 shutdownListenerList.remove(ShutdownListener.class, l);
189 }
190
191
192
193
194
195
196
197 public static void main(String[] args) {
198 if (args.length > 0) {
199 configurationURLAppArg = args[0];
200 }
201
202 if (OSXIntegration.IS_OSX) {
203 System.setProperty("apple.laf.useScreenMenuBar", "true");
204 }
205
206
207 LogManager.setRepositorySelector(() -> repositoryExImpl, repositorySelectorGuard);
208
209 final ApplicationPreferenceModel model = new ApplicationPreferenceModel();
210
211 SettingsManager.getInstance().configure(new ApplicationPreferenceModelSaver(model));
212
213 if (configurationURLAppArg != null) {
214 model.setBypassConfigurationURL(configurationURLAppArg);
215 }
216
217 EventQueue.invokeLater(() -> {
218 String lookAndFeelClassName = model.getLookAndFeelClassName();
219 if (lookAndFeelClassName == null || lookAndFeelClassName.trim().equals("")) {
220 String osName = System.getProperty("os.name");
221 if (osName.toLowerCase(Locale.ENGLISH).startsWith("mac")) {
222
223 } else if (osName.toLowerCase(Locale.ENGLISH).startsWith("windows")) {
224 lookAndFeelClassName = "com.sun.java.swing.plaf.windows.WindowsLookAndFeel";
225 model.setLookAndFeelClassName(lookAndFeelClassName);
226 } else if (osName.toLowerCase(Locale.ENGLISH).startsWith("linux")) {
227 lookAndFeelClassName = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
228 model.setLookAndFeelClassName(lookAndFeelClassName);
229 }
230 }
231
232 if (lookAndFeelClassName != null && !(lookAndFeelClassName.trim().equals(""))) {
233 loadLookAndFeelUsingPluginClassLoader(lookAndFeelClassName);
234 }
235 createChainsawGUI(model, null);
236 });
237 }
238
239
240
241
242
243
244
245
246
247 public static void createChainsawGUI(
248 ApplicationPreferenceModel model, Action newShutdownAction) {
249
250 if (model.isOkToRemoveSecurityManager()) {
251 MessageCenter
252 .getInstance()
253 .addMessage(
254 "User has authorised removal of Java Security Manager via preferences");
255 System.setSecurityManager(null);
256
257
258
259 Policy.setPolicy(new Policy() {
260
261 public void refresh() {
262 }
263
264 public PermissionCollection getPermissions(CodeSource codesource) {
265 Permissions perms = new Permissions();
266 perms.add(new AllPermission());
267 return (perms);
268 }
269 });
270 }
271
272 final LogUI logUI = new LogUI();
273 logUI.applicationPreferenceModel = model;
274
275 if (model.isShowSplash()) {
276 showSplash(logUI);
277 }
278 logUI.cyclicBufferSize = model.getCyclicBufferSize();
279 logUI.pluginRegistry = repositoryExImpl.getPluginRegistry();
280
281 logUI.handler = new ChainsawAppenderHandler();
282 logUI.handler.addEventBatchListener(logUI.new NewTabEventBatchReceiver());
283
284
285
286
287
288
289
290
291
292 logUI.ensureChainsawAppenderHandlerAdded();
293 logger = LogManager.getLogger(LogUI.class);
294
295
296
297 PropertyRewritePolicy policy = new PropertyRewritePolicy();
298 policy.setProperties("hostname=chainsaw,application=log,group=chainsaw");
299
300 RewriteAppender rewriteAppender = new RewriteAppender();
301 rewriteAppender.setRewritePolicy(policy);
302
303 Enumeration appenders = Logger.getLogger("org.apache").getAllAppenders();
304 if (!appenders.hasMoreElements()) {
305 appenders = Logger.getRootLogger().getAllAppenders();
306 }
307 while (appenders.hasMoreElements()) {
308 Appender nextAppender = (Appender) appenders.nextElement();
309 rewriteAppender.addAppender(nextAppender);
310 }
311 Logger.getLogger("org.apache").removeAllAppenders();
312 Logger.getLogger("org.apache").addAppender(rewriteAppender);
313 Logger.getLogger("org.apache").setAdditivity(false);
314
315
316 appenders = Logger.getLogger("httpclient").getAllAppenders();
317 if (!appenders.hasMoreElements()) {
318 appenders = Logger.getRootLogger().getAllAppenders();
319 }
320 while (appenders.hasMoreElements()) {
321 Appender nextAppender = (Appender) appenders.nextElement();
322 rewriteAppender.addAppender(nextAppender);
323 }
324 Logger.getLogger("httpclient").removeAllAppenders();
325 Logger.getLogger("httpclient").addAppender(rewriteAppender);
326 Logger.getLogger("httpclient").setAdditivity(false);
327
328
329 Logger.getLogger("org.apache.commons.vfs.cache").setLevel(Level.INFO);
330
331 Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
332 e.printStackTrace();
333 logger.error("Uncaught exception in thread " + t, e);
334 });
335
336 String config = configurationURLAppArg;
337 if (config != null) {
338 logger.info("Command-line configuration arg provided (overriding auto-configuration URL) - using: " + config);
339 } else {
340 config = model.getConfigurationURL();
341 }
342
343 if (config != null && (!config.trim().equals(""))) {
344 config = config.trim();
345 try {
346 URL configURL = new URL(config);
347 logger.info("Using '" + config + "' for auto-configuration");
348 logUI.loadConfigurationUsingPluginClassLoader(configURL);
349 } catch (MalformedURLException e) {
350 logger.error("Initial configuration - failed to convert config string to url", e);
351 } catch (IOException e) {
352 logger.error("Unable to access auto-configuration URL: " + config);
353 }
354 }
355
356
357
358 model.addPropertyChangeListener("configurationURL", evt -> {
359 String newConfiguration = evt.getNewValue().toString();
360 if (newConfiguration != null && !(newConfiguration.trim().equals(""))) {
361 newConfiguration = newConfiguration.trim();
362 try {
363 logger.info("loading updated configuration: " + newConfiguration);
364 URL newConfigurationURL = new URL(newConfiguration);
365 File file = new File(newConfigurationURL.toURI());
366 if (file.exists()) {
367 logUI.loadConfigurationUsingPluginClassLoader(newConfigurationURL);
368 } else {
369 logger.info("Updated configuration but file does not exist");
370 }
371 } catch (MalformedURLException | URISyntaxException e) {
372 logger.error("Updated configuration - failed to convert config string to URL", e);
373 }
374 }
375 });
376
377 LogManager.getRootLogger().setLevel(Level.TRACE);
378 EventQueue.invokeLater(logUI::activateViewer);
379
380 logger.info("SecurityManager is now: " + System.getSecurityManager());
381
382 if (newShutdownAction != null) {
383 logUI.setShutdownAction(newShutdownAction);
384 } else {
385 logUI.setShutdownAction(
386 new AbstractAction() {
387 public void actionPerformed(ActionEvent e) {
388 System.exit(0);
389 }
390 });
391 }
392 }
393
394
395
396
397
398
399
400 public void activateViewer(ChainsawAppender appender) {
401
402 if (OSXIntegration.IS_OSX) {
403 System.setProperty("apple.laf.useScreenMenuBar", "true");
404 }
405
406 LogManager.setRepositorySelector(() -> repositoryExImpl, repositorySelectorGuard);
407
408
409 LogManager.getRootLogger().setLevel(Level.TRACE);
410
411 final ApplicationPreferenceModel model = new ApplicationPreferenceModel();
412 SettingsManager.getInstance().configure(new ApplicationPreferenceModelSaver(model));
413
414 cyclicBufferSize = model.getCyclicBufferSize();
415
416 handler = new ChainsawAppenderHandler(appender);
417 handler.addEventBatchListener(new NewTabEventBatchReceiver());
418
419 logger = LogManager.getLogger(LogUI.class);
420
421 setShutdownAction(
422 new AbstractAction() {
423 public void actionPerformed(ActionEvent e) {
424 }
425 });
426
427 applicationPreferenceModel = new ApplicationPreferenceModel();
428
429 SettingsManager.getInstance().configure(new ApplicationPreferenceModelSaver(model));
430
431 EventQueue.invokeLater(() -> {
432 loadLookAndFeelUsingPluginClassLoader(model.getLookAndFeelClassName());
433 createChainsawGUI(model, null);
434 getApplicationPreferenceModel().apply(model);
435 activateViewer();
436 });
437 }
438
439
440
441
442
443 private void initGUI() {
444
445 setupHelpSystem();
446 statusBar = new ChainsawStatusBar(this);
447 setupReceiverPanel();
448
449 setToolBarAndMenus(new ChainsawToolBarAndMenus(this));
450 toolbar = getToolBarAndMenus().getToolbar();
451 setJMenuBar(getToolBarAndMenus().getMenubar());
452
453 setTabbedPane(new ChainsawTabbedPane());
454 getSettingsManager().addSettingsListener(getTabbedPane());
455 getSettingsManager().configure(getTabbedPane());
456
457
458
459
460 FileDnDTarget dnDTarget = new FileDnDTarget(tabbedPane);
461 dnDTarget.addPropertyChangeListener("fileList", evt -> {
462 final List fileList = (List) evt.getNewValue();
463
464 Thread thread = new Thread(() -> {
465 logger.debug("Loading files: " + fileList);
466 for (Object aFileList : fileList) {
467 File file = (File) aFileList;
468 final Decoder decoder = new XMLDecoder();
469 try {
470 getStatusBar().setMessage("Loading " + file.getAbsolutePath() + "...");
471 FileLoadAction.importURL(handler, decoder, file
472 .getName(), file.toURI().toURL());
473 } catch (Exception e) {
474 String errorMsg = "Failed to import a file";
475 logger.error(errorMsg, e);
476 getStatusBar().setMessage(errorMsg);
477 }
478 }
479
480 });
481
482 thread.setPriority(Thread.MIN_PRIORITY);
483 thread.start();
484
485 });
486
487 applicationPreferenceModelPanel = new ApplicationPreferenceModelPanel(applicationPreferenceModel);
488
489 applicationPreferenceModelPanel.setOkCancelActionListener(
490 e -> preferencesFrame.setVisible(false));
491 KeyStroke escape = KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0, false);
492 Action closeAction = new AbstractAction() {
493 public void actionPerformed(ActionEvent e) {
494 preferencesFrame.setVisible(false);
495 }
496 };
497 preferencesFrame.getRootPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(escape, "ESCAPE");
498 preferencesFrame.getRootPane().
499 getActionMap().put("ESCAPE", closeAction);
500
501 OSXIntegration.init(this);
502
503 }
504
505 private void initPlugins(PluginRegistry pluginRegistry) {
506 pluginRegistry.addPluginListener(
507 new PluginListener() {
508 public void pluginStarted(PluginEvent e) {
509 if (e.getPlugin() instanceof JComponent) {
510 JComponent plugin = (JComponent) e.getPlugin();
511 getTabbedPane().addANewTab(plugin.getName(), plugin, null, null);
512 getPanelMap().put(plugin.getName(), plugin);
513 }
514 }
515
516 public void pluginStopped(PluginEvent e) {
517
518 }
519 });
520
521
522
523
524
525
526 try {
527 Class<? extends Plugin> pluginClass = Class.forName("org.apache.log4j.chainsaw.zeroconf.ZeroConfPlugin").asSubclass(Plugin.class);
528 Plugin plugin = pluginClass.newInstance();
529 pluginRegistry.addPlugin(plugin);
530 plugin.activateOptions();
531 MessageCenter.getInstance().getLogger().info("Looks like ZeroConf is available... WooHoo!");
532 } catch (Throwable e) {
533 MessageCenter.getInstance().getLogger().error("Doesn't look like ZeroConf is available", e);
534 }
535 }
536
537 private void setupReceiverPanel() {
538 receiversPanel = new ReceiversPanel();
539 receiversPanel.addPropertyChangeListener(
540 "visible",
541 evt -> getApplicationPreferenceModel().setReceivers(
542 (Boolean) evt.getNewValue()));
543 }
544
545
546
547
548 private void setupHelpSystem() {
549 welcomePanel = new WelcomePanel();
550
551 JToolBar tb = welcomePanel.getToolbar();
552
553
554 tb.add(
555 new SmallButton(
556 new AbstractAction("Tutorial", new ImageIcon(ChainsawIcons.HELP)) {
557 public void actionPerformed(ActionEvent e) {
558 setupTutorial();
559 }
560 }));
561 tb.addSeparator();
562
563 final Action exampleConfigAction =
564 new AbstractAction("View example Receiver configuration") {
565 public void actionPerformed(ActionEvent e) {
566 HelpManager.getInstance().setHelpURL(
567 ChainsawConstants.EXAMPLE_CONFIG_URL);
568 }
569 };
570
571 exampleConfigAction.putValue(
572 Action.SHORT_DESCRIPTION,
573 "Displays an example Log4j configuration file with several Receivers defined.");
574
575 JButton exampleButton = new SmallButton(exampleConfigAction);
576 tb.add(exampleButton);
577
578 tb.add(Box.createHorizontalGlue());
579
580
581
582
583
584 HelpManager.getInstance().addPropertyChangeListener(
585 "helpURL",
586 evt -> {
587 URL newURL = (URL) evt.getNewValue();
588
589 if (newURL != null) {
590 welcomePanel.setURL(newURL);
591 ensureWelcomePanelVisible();
592 }
593 });
594 }
595
596 private void ensureWelcomePanelVisible() {
597
598 if (!getTabbedPane().containsWelcomePanel()) {
599 addWelcomePanel();
600 }
601 getTabbedPane().setSelectedComponent(welcomePanel);
602 }
603
604
605
606
607
608
609
610 public void loadSettings(LoadSettingsEvent event) {
611 setLocation(
612 event.asInt(LogUI.MAIN_WINDOW_X), event.asInt(LogUI.MAIN_WINDOW_Y));
613 int width = event.asInt(LogUI.MAIN_WINDOW_WIDTH);
614 int height = event.asInt(LogUI.MAIN_WINDOW_HEIGHT);
615 if (width == -1 && height == -1) {
616 width = Toolkit.getDefaultToolkit().getScreenSize().width;
617 height = Toolkit.getDefaultToolkit().getScreenSize().height;
618 setSize(width, height);
619 setExtendedState(getExtendedState() | MAXIMIZED_BOTH);
620 } else {
621 setSize(width, height);
622 }
623
624 getToolBarAndMenus().stateChange();
625 RuleColorizer colorizer = new RuleColorizer();
626 colorizer.loadColorSettings(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
627 allColorizers.put(ChainsawConstants.DEFAULT_COLOR_RULE_NAME, colorizer);
628 if (event.getSetting("SavedConfig.logFormat") != null) {
629 receiverConfigurationPanel.getModel().setLogFormat(event.getSetting("SavedConfig.logFormat"));
630 }
631 }
632
633
634
635
636
637
638 public void saveSettings(SaveSettingsEvent event) {
639 event.saveSetting(LogUI.MAIN_WINDOW_X, (int) getLocation().getX());
640 event.saveSetting(LogUI.MAIN_WINDOW_Y, (int) getLocation().getY());
641
642 event.saveSetting(LogUI.MAIN_WINDOW_WIDTH, getWidth());
643 event.saveSetting(LogUI.MAIN_WINDOW_HEIGHT, getHeight());
644 RuleColorizer colorizer = allColorizers.get(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
645 colorizer.saveColorSettings(ChainsawConstants.DEFAULT_COLOR_RULE_NAME);
646 if (receiverConfigurationPanel.getModel().getLogFormat() != null) {
647 event.saveSetting("SavedConfig.logFormat", receiverConfigurationPanel.getModel().getLogFormat());
648 }
649 }
650
651
652
653
654
655
656 public void activateViewer() {
657 LoggerRepository repo = LogManager.getLoggerRepository();
658 if (repo instanceof LoggerRepositoryEx) {
659 this.pluginRegistry = ((LoggerRepositoryEx) repo).getPluginRegistry();
660 }
661 initGUI();
662
663 initPrefModelListeners();
664
665
666
667
668
669 MessageCenter.getInstance().getLogger().addAppender(
670 new AppenderSkeleton() {
671 protected void append(LoggingEvent event) {
672 getStatusBar().setMessage(event.getMessage().toString());
673 }
674
675 public void close() {
676 }
677
678 public boolean requiresLayout() {
679 return false;
680 }
681 });
682
683
684 initSocketConnectionListener();
685
686 if (pluginRegistry.getPlugins(Receiver.class).size() == 0) {
687 noReceiversDefined = true;
688 }
689
690 getFilterableColumns().add(ChainsawConstants.LEVEL_COL_NAME);
691 getFilterableColumns().add(ChainsawConstants.LOGGER_COL_NAME);
692 getFilterableColumns().add(ChainsawConstants.THREAD_COL_NAME);
693 getFilterableColumns().add(ChainsawConstants.NDC_COL_NAME);
694 getFilterableColumns().add(ChainsawConstants.PROPERTIES_COL_NAME);
695 getFilterableColumns().add(ChainsawConstants.CLASS_COL_NAME);
696 getFilterableColumns().add(ChainsawConstants.METHOD_COL_NAME);
697 getFilterableColumns().add(ChainsawConstants.FILE_COL_NAME);
698 getFilterableColumns().add(ChainsawConstants.NONE_COL_NAME);
699
700 JPanel panePanel = new JPanel();
701 panePanel.setLayout(new BorderLayout(2, 2));
702
703 getContentPane().setLayout(new BorderLayout());
704
705 getTabbedPane().addChangeListener(getToolBarAndMenus());
706 getTabbedPane().addChangeListener(e -> {
707 LogPanel thisLogPanel = getCurrentLogPanel();
708 if (thisLogPanel != null) {
709 thisLogPanel.updateStatusBar();
710 }
711 });
712
713 KeyStroke ksRight =
714 KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
715 KeyStroke ksLeft =
716 KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
717 KeyStroke ksGotoLine =
718 KeyStroke.getKeyStroke(KeyEvent.VK_G, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask());
719
720 getTabbedPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
721 ksRight, "MoveRight");
722 getTabbedPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
723 ksLeft, "MoveLeft");
724 getTabbedPane().getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW).put(
725 ksGotoLine, "GotoLine");
726
727 Action moveRight =
728 new AbstractAction() {
729 public void actionPerformed(ActionEvent e) {
730 int temp = getTabbedPane().getSelectedIndex();
731 ++temp;
732
733 if (temp != getTabbedPane().getTabCount()) {
734 getTabbedPane().setSelectedTab(temp);
735 }
736 }
737 };
738
739 Action moveLeft =
740 new AbstractAction() {
741 public void actionPerformed(ActionEvent e) {
742 int temp = getTabbedPane().getSelectedIndex();
743 --temp;
744
745 if (temp > -1) {
746 getTabbedPane().setSelectedTab(temp);
747 }
748 }
749 };
750
751 Action gotoLine =
752 new AbstractAction() {
753 public void actionPerformed(ActionEvent e) {
754 String inputLine = JOptionPane.showInputDialog(LogUI.this, "Enter the line number to go:", "Goto Line", JOptionPane.PLAIN_MESSAGE);
755 try {
756 int lineNumber = Integer.parseInt(inputLine);
757 int row = getCurrentLogPanel().setSelectedEvent(lineNumber);
758 if (row == -1) {
759 JOptionPane.showMessageDialog(LogUI.this, "You have entered an invalid line number", "Error", JOptionPane.ERROR_MESSAGE);
760 }
761 } catch (NumberFormatException nfe) {
762 JOptionPane.showMessageDialog(LogUI.this, "You have entered an invalid line number", "Error", JOptionPane.ERROR_MESSAGE);
763 }
764 }
765 };
766
767
768 getTabbedPane().getActionMap().put("MoveRight", moveRight);
769 getTabbedPane().getActionMap().put("MoveLeft", moveLeft);
770 getTabbedPane().getActionMap().put("GotoLine", gotoLine);
771
772
773
774
775
776 getTabbedPane().addMouseListener(
777 new MouseAdapter() {
778 public void mouseClicked(MouseEvent e) {
779 super.mouseClicked(e);
780
781 if (
782 (e.getClickCount() > 1)
783 && ((e.getModifiers() & InputEvent.BUTTON1_MASK) > 0)) {
784 int tabIndex = getTabbedPane().getSelectedIndex();
785
786 if (
787 (tabIndex != -1)
788 && (tabIndex == getTabbedPane().getSelectedIndex())) {
789 LogPanel logPanel = getCurrentLogPanel();
790
791 if (logPanel != null) {
792 logPanel.undock();
793 }
794 }
795 }
796 }
797 });
798
799 panePanel.add(getTabbedPane());
800 addWelcomePanel();
801
802 getContentPane().add(toolbar, BorderLayout.NORTH);
803 getContentPane().add(statusBar, BorderLayout.SOUTH);
804
805 mainReceiverSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, panePanel, receiversPanel);
806 dividerSize = mainReceiverSplitPane.getDividerSize();
807 mainReceiverSplitPane.setDividerLocation(-1);
808
809 getContentPane().add(mainReceiverSplitPane, BorderLayout.CENTER);
810
811
812
813
814
815
816 initPlugins(pluginRegistry);
817
818 mainReceiverSplitPane.setResizeWeight(1.0);
819 addWindowListener(
820 new WindowAdapter() {
821 public void windowClosing(WindowEvent event) {
822 exit();
823 }
824 });
825 preferencesFrame.setTitle("'Application-wide Preferences");
826 preferencesFrame.setIconImage(
827 ((ImageIcon) ChainsawIcons.ICON_PREFERENCES).getImage());
828 preferencesFrame.getContentPane().add(applicationPreferenceModelPanel);
829
830 preferencesFrame.setSize(750, 520);
831
832 Dimension screenDimension = Toolkit.getDefaultToolkit().getScreenSize();
833 preferencesFrame.setLocation(
834 new Point(
835 (screenDimension.width / 2) - (preferencesFrame.getSize().width / 2),
836 (screenDimension.height / 2) - (preferencesFrame.getSize().height / 2)));
837
838 pack();
839
840 final JPopupMenu tabPopup = new JPopupMenu();
841 final Action hideCurrentTabAction =
842 new AbstractAction("Hide") {
843 public void actionPerformed(ActionEvent e) {
844 Component selectedComp = getTabbedPane().getSelectedComponent();
845 if (selectedComp instanceof LogPanel) {
846 displayPanel(getCurrentLogPanel().getIdentifier(), false);
847 tbms.stateChange();
848 } else {
849 getTabbedPane().remove(selectedComp);
850 }
851 }
852 };
853
854 final Action hideOtherTabsAction =
855 new AbstractAction("Hide Others") {
856 public void actionPerformed(ActionEvent e) {
857 Component selectedComp = getTabbedPane().getSelectedComponent();
858 String currentName;
859 if (selectedComp instanceof LogPanel) {
860 currentName = getCurrentLogPanel().getIdentifier();
861 } else if (selectedComp instanceof WelcomePanel) {
862 currentName = ChainsawTabbedPane.WELCOME_TAB;
863 } else {
864 currentName = ChainsawTabbedPane.ZEROCONF;
865 }
866
867 int count = getTabbedPane().getTabCount();
868 int index = 0;
869
870 for (int i = 0; i < count; i++) {
871 String name = getTabbedPane().getTitleAt(index);
872
873 if (
874 getPanelMap().keySet().contains(name)
875 && !name.equals(currentName)) {
876 displayPanel(name, false);
877 tbms.stateChange();
878 } else {
879 index++;
880 }
881 }
882 }
883 };
884
885 Action showHiddenTabsAction =
886 new AbstractAction("Show All Hidden") {
887 public void actionPerformed(ActionEvent e) {
888 for (Object o : getPanels().entrySet()) {
889 Map.Entry entry = (Map.Entry) o;
890 Boolean docked = (Boolean) entry.getValue();
891 if (docked) {
892 String identifier = (String) entry.getKey();
893 int count = getTabbedPane().getTabCount();
894 boolean found = false;
895
896 for (int i = 0; i < count; i++) {
897 String name = getTabbedPane().getTitleAt(i);
898
899 if (name.equals(identifier)) {
900 found = true;
901
902 break;
903 }
904 }
905
906 if (!found) {
907 displayPanel(identifier, true);
908 tbms.stateChange();
909 }
910 }
911 }
912 }
913 };
914
915 tabPopup.add(hideCurrentTabAction);
916 tabPopup.add(hideOtherTabsAction);
917 tabPopup.addSeparator();
918 tabPopup.add(showHiddenTabsAction);
919
920 final PopupListener tabPopupListener = new PopupListener(tabPopup);
921 getTabbedPane().addMouseListener(tabPopupListener);
922
923 this.handler.addPropertyChangeListener(
924 "dataRate",
925 evt -> {
926 double dataRate = (Double) evt.getNewValue();
927 statusBar.setDataRate(dataRate);
928 });
929
930 getSettingsManager().addSettingsListener(this);
931 getSettingsManager().addSettingsListener(MRUFileListPreferenceSaver.getInstance());
932 getSettingsManager().addSettingsListener(receiversPanel);
933 try {
934
935 getSettingsManager().loadSettings();
936 } catch (Exception e) {
937 e.printStackTrace();
938 }
939
940
941 getSettingsManager().addSettingsListener(new ApplicationPreferenceModelSaver(applicationPreferenceModel));
942
943 setVisible(true);
944
945 if (applicationPreferenceModel.isReceivers()) {
946 showReceiverPanel();
947 } else {
948 hideReceiverPanel();
949 }
950
951 removeSplash();
952
953 synchronized (initializationLock) {
954 isGUIFullyInitialized = true;
955 initializationLock.notifyAll();
956 }
957
958 if (
959 noReceiversDefined
960 && applicationPreferenceModel.isShowNoReceiverWarning()) {
961 SwingHelper.invokeOnEDT(this::showReceiverConfigurationPanel);
962 }
963
964 Container container = tutorialFrame.getContentPane();
965 final JEditorPane tutorialArea = new JEditorPane();
966 tutorialArea.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));
967 tutorialArea.setEditable(false);
968 container.setLayout(new BorderLayout());
969
970 try {
971 tutorialArea.setPage(ChainsawConstants.TUTORIAL_URL);
972 JTextComponentFormatter.applySystemFontAndSize(tutorialArea);
973
974 container.add(new JScrollPane(tutorialArea), BorderLayout.CENTER);
975 } catch (Exception e) {
976 MessageCenter.getInstance().getLogger().error(
977 "Error occurred loading the Tutorial", e);
978 }
979
980 tutorialFrame.setIconImage(new ImageIcon(ChainsawIcons.HELP).getImage());
981 tutorialFrame.setSize(new Dimension(640, 480));
982
983 final Action startTutorial =
984 new AbstractAction(
985 "Start Tutorial", new ImageIcon(ChainsawIcons.ICON_RESUME_RECEIVER)) {
986 public void actionPerformed(ActionEvent e) {
987 if (
988 JOptionPane.showConfirmDialog(
989 null,
990 "This will start 3 \"Generator\" receivers for use in the Tutorial. Is that ok?",
991 "Confirm", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
992 new Thread(new Tutorial()).start();
993 putValue("TutorialStarted", Boolean.TRUE);
994 } else {
995 putValue("TutorialStarted", Boolean.FALSE);
996 }
997 }
998 };
999
1000 final Action stopTutorial =
1001 new AbstractAction(
1002 "Stop Tutorial", new ImageIcon(ChainsawIcons.ICON_STOP_RECEIVER)) {
1003 public void actionPerformed(ActionEvent e) {
1004 if (
1005 JOptionPane.showConfirmDialog(
1006 null,
1007 "This will stop all of the \"Generator\" receivers used in the Tutorial, but leave any other Receiver untouched. Is that ok?",
1008 "Confirm", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
1009 new Thread(
1010 () -> {
1011 LoggerRepository repo1 = LogManager.getLoggerRepository();
1012 if (repo1 instanceof LoggerRepositoryEx) {
1013 PluginRegistry pluginRegistry = ((LoggerRepositoryEx) repo1).getPluginRegistry();
1014 List list = pluginRegistry.getPlugins(Generator.class);
1015
1016 for (Object aList : list) {
1017 Plugin plugin = (Plugin) aList;
1018 pluginRegistry.stopPlugin(plugin.getName());
1019 }
1020 }
1021 }).start();
1022 setEnabled(false);
1023 startTutorial.putValue("TutorialStarted", Boolean.FALSE);
1024 }
1025 }
1026 };
1027
1028 stopTutorial.putValue(
1029 Action.SHORT_DESCRIPTION,
1030 "Removes all of the Tutorials Generator Receivers, leaving all other Receivers untouched");
1031 startTutorial.putValue(
1032 Action.SHORT_DESCRIPTION,
1033 "Begins the Tutorial, starting up some Generator Receivers so you can see Chainsaw in action");
1034 stopTutorial.setEnabled(false);
1035
1036 final SmallToggleButton startButton = new SmallToggleButton(startTutorial);
1037 PropertyChangeListener pcl =
1038 evt -> {
1039 stopTutorial.setEnabled(
1040 startTutorial.getValue("TutorialStarted").equals(Boolean.TRUE));
1041 startButton.setSelected(stopTutorial.isEnabled());
1042 };
1043
1044 startTutorial.addPropertyChangeListener(pcl);
1045 stopTutorial.addPropertyChangeListener(pcl);
1046
1047 pluginRegistry.addPluginListener(
1048 new PluginListener() {
1049 public void pluginStarted(PluginEvent e) {
1050 }
1051
1052 public void pluginStopped(PluginEvent e) {
1053 List list = pluginRegistry.getPlugins(Generator.class);
1054
1055 if (list.size() == 0) {
1056 startTutorial.putValue("TutorialStarted", Boolean.FALSE);
1057 }
1058 }
1059 });
1060
1061 final SmallButton stopButton = new SmallButton(stopTutorial);
1062
1063 final JToolBar tutorialToolbar = new JToolBar();
1064 tutorialToolbar.setFloatable(false);
1065 tutorialToolbar.add(startButton);
1066 tutorialToolbar.add(stopButton);
1067 container.add(tutorialToolbar, BorderLayout.NORTH);
1068 tutorialArea.addHyperlinkListener(
1069 e -> {
1070 if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
1071 if (e.getDescription().equals("StartTutorial")) {
1072 startTutorial.actionPerformed(null);
1073 } else if (e.getDescription().equals("StopTutorial")) {
1074 stopTutorial.actionPerformed(null);
1075 } else {
1076 try {
1077 tutorialArea.setPage(e.getURL());
1078 } catch (IOException e1) {
1079 MessageCenter.getInstance().getLogger().error(
1080 "Failed to change the URL for the Tutorial", e1);
1081 }
1082 }
1083 }
1084 });
1085
1086
1087
1088
1089
1090
1091 if (!getTabbedPane().tabSetting.isWelcome()) {
1092 displayPanel(ChainsawTabbedPane.WELCOME_TAB, false);
1093 }
1094 if (!getTabbedPane().tabSetting.isZeroconf()) {
1095 displayPanel(ChainsawTabbedPane.ZEROCONF, false);
1096 }
1097 tbms.stateChange();
1098
1099 }
1100
1101
1102
1103
1104 private void showReceiverPanel() {
1105 mainReceiverSplitPane.setDividerSize(dividerSize);
1106 mainReceiverSplitPane.setDividerLocation(lastMainReceiverSplitLocation);
1107 receiversPanel.setVisible(true);
1108 mainReceiverSplitPane.repaint();
1109 }
1110
1111
1112
1113
1114 private void hideReceiverPanel() {
1115
1116 int currentSize = mainReceiverSplitPane.getWidth() - mainReceiverSplitPane.getDividerSize();
1117 if (mainReceiverSplitPane.getDividerLocation() > -1) {
1118 if (!(((mainReceiverSplitPane.getDividerLocation() + 1) == currentSize)
1119 || ((mainReceiverSplitPane.getDividerLocation() - 1) == 0))) {
1120 lastMainReceiverSplitLocation = ((double) mainReceiverSplitPane
1121 .getDividerLocation() / currentSize);
1122 }
1123 }
1124 mainReceiverSplitPane.setDividerSize(0);
1125 receiversPanel.setVisible(false);
1126 mainReceiverSplitPane.repaint();
1127 }
1128
1129 private void initSocketConnectionListener() {
1130 final SocketNodeEventListener socketListener =
1131 new SocketNodeEventListener() {
1132 public void socketOpened(String remoteInfo) {
1133 statusBar.remoteConnectionReceived(remoteInfo);
1134 }
1135
1136 public void socketClosedEvent(Exception e) {
1137 MessageCenter.getInstance().getLogger().info(
1138 "Connection lost! :: " + e.getMessage());
1139 }
1140 };
1141
1142 PluginListener pluginListener =
1143 new PluginListener() {
1144 public void pluginStarted(PluginEvent e) {
1145 MessageCenter.getInstance().getLogger().info(
1146 e.getPlugin().getName() + " started!");
1147
1148 Method method = getAddListenerMethod(e.getPlugin());
1149
1150 if (method != null) {
1151 try {
1152 method.invoke(e.getPlugin(), socketListener);
1153 } catch (Exception ex) {
1154 MessageCenter.getInstance().getLogger().error(
1155 "Failed to add a SocketNodeEventListener", ex);
1156 }
1157 }
1158 }
1159
1160 Method getRemoveListenerMethod(Plugin p) {
1161 try {
1162 return p.getClass().getMethod(
1163 "removeSocketNodeEventListener",
1164 SocketNodeEventListener.class);
1165 } catch (Exception e) {
1166 return null;
1167 }
1168 }
1169
1170 Method getAddListenerMethod(Plugin p) {
1171 try {
1172 return p.getClass().getMethod(
1173 "addSocketNodeEventListener",
1174 SocketNodeEventListener.class);
1175 } catch (Exception e) {
1176 return null;
1177 }
1178 }
1179
1180 public void pluginStopped(PluginEvent e) {
1181 Method method = getRemoveListenerMethod(e.getPlugin());
1182
1183 if (method != null) {
1184 try {
1185 method.invoke(e.getPlugin(), socketListener);
1186 } catch (Exception ex) {
1187 MessageCenter.getInstance().getLogger().error(
1188 "Failed to remove SocketNodeEventListener", ex);
1189 }
1190 }
1191
1192 MessageCenter.getInstance().getLogger().info(
1193 e.getPlugin().getName() + " stopped!");
1194 }
1195 };
1196
1197 pluginRegistry.addPluginListener(pluginListener);
1198 }
1199
1200 private void initPrefModelListeners() {
1201 applicationPreferenceModel.addPropertyChangeListener(
1202 "identifierExpression",
1203 evt -> handler.setIdentifierExpression(evt.getNewValue().toString()));
1204 handler.setIdentifierExpression(applicationPreferenceModel.getIdentifierExpression());
1205
1206
1207 applicationPreferenceModel.addPropertyChangeListener(
1208 "toolTipDisplayMillis",
1209 evt -> ToolTipManager.sharedInstance().setDismissDelay(
1210 (Integer) evt.getNewValue()));
1211 ToolTipManager.sharedInstance().setDismissDelay(
1212 applicationPreferenceModel.getToolTipDisplayMillis());
1213
1214 applicationPreferenceModel.addPropertyChangeListener(
1215 "responsiveness",
1216 evt -> {
1217 int value = (Integer) evt.getNewValue();
1218 handler.setQueueInterval((value * 1000) - 750);
1219 });
1220 handler.setQueueInterval((applicationPreferenceModel.getResponsiveness() * 1000) - 750);
1221
1222 applicationPreferenceModel.addPropertyChangeListener(
1223 "tabPlacement",
1224 evt -> SwingUtilities.invokeLater(
1225 () -> {
1226 int placement = (Integer) evt.getNewValue();
1227
1228 switch (placement) {
1229 case SwingConstants.TOP:
1230 case SwingConstants.BOTTOM:
1231 tabbedPane.setTabPlacement(placement);
1232
1233 break;
1234
1235 default:
1236 break;
1237 }
1238 }));
1239
1240 applicationPreferenceModel.addPropertyChangeListener(
1241 "statusBar",
1242 evt -> {
1243 boolean value = (Boolean) evt.getNewValue();
1244 setStatusBarVisible(value);
1245 });
1246 setStatusBarVisible(applicationPreferenceModel.isStatusBar());
1247
1248 applicationPreferenceModel.addPropertyChangeListener(
1249 "receivers",
1250 evt -> {
1251 boolean value = (Boolean) evt.getNewValue();
1252
1253 if (value) {
1254 showReceiverPanel();
1255 } else {
1256 hideReceiverPanel();
1257 }
1258 });
1259
1260
1261
1262
1263
1264
1265
1266 applicationPreferenceModel.addPropertyChangeListener(
1267 "toolbar",
1268 evt -> {
1269 boolean value = (Boolean) evt.getNewValue();
1270 toolbar.setVisible(value);
1271 });
1272 toolbar.setVisible(applicationPreferenceModel.isToolbar());
1273
1274 }
1275
1276
1277
1278
1279 private void showReceiverConfigurationPanel() {
1280 SwingUtilities.invokeLater(
1281 () -> {
1282 final JDialog dialog = new JDialog(LogUI.this, true);
1283 dialog.setTitle("Load events into Chainsaw");
1284 dialog.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
1285
1286 dialog.setResizable(false);
1287
1288 receiverConfigurationPanel.setCompletionActionListener(
1289 e -> {
1290 dialog.setVisible(false);
1291
1292 if (receiverConfigurationPanel.getModel().isCancelled()) {
1293 return;
1294 }
1295 applicationPreferenceModel.setShowNoReceiverWarning(!receiverConfigurationPanel.isDontWarnMeAgain());
1296
1297 List<Plugin> plugins = pluginRegistry.getPlugins();
1298 for (Object plugin1 : plugins) {
1299 Plugin plugin = (Plugin) plugin1;
1300
1301 if (!plugin.getName().toLowerCase(Locale.ENGLISH).contains("zeroconf")) {
1302 pluginRegistry.stopPlugin(plugin.getName());
1303 }
1304 }
1305 URL configURL = null;
1306
1307 if (receiverConfigurationPanel.getModel().isNetworkReceiverMode()) {
1308 int port = receiverConfigurationPanel.getModel().getNetworkReceiverPort();
1309
1310 try {
1311 Class<? extends Receiver> receiverClass = receiverConfigurationPanel.getModel().getNetworkReceiverClass();
1312 Receiver networkReceiver = receiverClass.newInstance();
1313 networkReceiver.setName(receiverClass.getSimpleName() + "-" + port);
1314
1315 Method portMethod =
1316 networkReceiver.getClass().getMethod(
1317 "setPort", int.class);
1318 portMethod.invoke(
1319 networkReceiver, port);
1320
1321 networkReceiver.setThreshold(Level.TRACE);
1322
1323 pluginRegistry.addPlugin(networkReceiver);
1324 networkReceiver.activateOptions();
1325 receiversPanel.updateReceiverTreeInDispatchThread();
1326 } catch (Exception e3) {
1327 MessageCenter.getInstance().getLogger().error(
1328 "Error creating Receiver", e3);
1329 MessageCenter.getInstance().getLogger().info(
1330 "An error occurred creating your Receiver");
1331 }
1332 } else if (receiverConfigurationPanel.getModel().isLog4jConfig()) {
1333 File log4jConfigFile = receiverConfigurationPanel.getModel().getLog4jConfigFile();
1334 if (log4jConfigFile != null) {
1335 try {
1336 Map<String, Map<String, String>> entries = LogFilePatternLayoutBuilder.getAppenderConfiguration(log4jConfigFile);
1337 for (Object o : entries.entrySet()) {
1338 try {
1339 Map.Entry entry = (Map.Entry) o;
1340 String name = (String) entry.getKey();
1341 Map values = (Map) entry.getValue();
1342
1343 String conversionPattern = values.get("conversion").toString();
1344 File file = new File(values.get("file").toString());
1345 URL fileURL = file.toURI().toURL();
1346 String timestampFormat = LogFilePatternLayoutBuilder.getTimeStampFormat(conversionPattern);
1347 String receiverPattern = LogFilePatternLayoutBuilder.getLogFormatFromPatternLayout(conversionPattern);
1348 VFSLogFilePatternReceiver fileReceiver = new VFSLogFilePatternReceiver();
1349 fileReceiver.setName(name);
1350 fileReceiver.setAutoReconnect(true);
1351 fileReceiver.setContainer(LogUI.this);
1352 fileReceiver.setAppendNonMatches(true);
1353 fileReceiver.setFileURL(fileURL.toURI().toString());
1354 fileReceiver.setTailing(true);
1355 fileReceiver.setLogFormat(receiverPattern);
1356 fileReceiver.setTimestampFormat(timestampFormat);
1357 fileReceiver.setThreshold(Level.TRACE);
1358 pluginRegistry.addPlugin(fileReceiver);
1359 fileReceiver.activateOptions();
1360 receiversPanel.updateReceiverTreeInDispatchThread();
1361 } catch (URISyntaxException e1) {
1362 e1.printStackTrace();
1363 }
1364 }
1365 } catch (IOException e1) {
1366 e1.printStackTrace();
1367 }
1368 }
1369 } else if (receiverConfigurationPanel.getModel().isLoadConfig()) {
1370 configURL = receiverConfigurationPanel.getModel().getConfigToLoad();
1371 } else if (receiverConfigurationPanel.getModel().isLogFileReceiverConfig()) {
1372 try {
1373 URL fileURL = receiverConfigurationPanel.getModel().getLogFileURL();
1374 if (fileURL != null) {
1375 VFSLogFilePatternReceiver fileReceiver = new VFSLogFilePatternReceiver();
1376 fileReceiver.setName(fileURL.getFile());
1377 fileReceiver.setAutoReconnect(true);
1378 fileReceiver.setContainer(LogUI.this);
1379 fileReceiver.setAppendNonMatches(true);
1380 fileReceiver.setFileURL(fileURL.toURI().toString());
1381 fileReceiver.setTailing(true);
1382 if (receiverConfigurationPanel.getModel().isPatternLayoutLogFormat()) {
1383 fileReceiver.setLogFormat(LogFilePatternLayoutBuilder.getLogFormatFromPatternLayout(receiverConfigurationPanel.getModel().getLogFormat()));
1384 } else {
1385 fileReceiver.setLogFormat(receiverConfigurationPanel.getModel().getLogFormat());
1386 }
1387 fileReceiver.setTimestampFormat(receiverConfigurationPanel.getModel().getLogFormatTimestampFormat());
1388 fileReceiver.setThreshold(Level.TRACE);
1389
1390 pluginRegistry.addPlugin(fileReceiver);
1391 fileReceiver.activateOptions();
1392 receiversPanel.updateReceiverTreeInDispatchThread();
1393 }
1394 } catch (Exception e2) {
1395 MessageCenter.getInstance().getLogger().error(
1396 "Error creating Receiver", e2);
1397 MessageCenter.getInstance().getLogger().info(
1398 "An error occurred creating your Receiver");
1399 }
1400 }
1401 if (configURL == null && receiverConfigurationPanel.isDontWarnMeAgain()) {
1402
1403 if (receiverConfigurationPanel.getModel().getSaveConfigFile() != null) {
1404 try {
1405 configURL = receiverConfigurationPanel.getModel().getSaveConfigFile().toURI().toURL();
1406 } catch (MalformedURLException e1) {
1407 e1.printStackTrace();
1408 }
1409 } else {
1410
1411 configURL = receiverConfigurationPanel.getModel().getDefaultConfigFileURL();
1412 }
1413 }
1414 if (configURL != null) {
1415 MessageCenter.getInstance().getLogger().debug(
1416 "Initialiazing Log4j with " + configURL.toExternalForm());
1417 final URL finalURL = configURL;
1418 new Thread(
1419 () -> {
1420 if (receiverConfigurationPanel.isDontWarnMeAgain()) {
1421 applicationPreferenceModel.setConfigurationURL(finalURL.toExternalForm());
1422 } else {
1423 try {
1424 if (new File(finalURL.toURI()).exists()) {
1425 loadConfigurationUsingPluginClassLoader(finalURL);
1426 }
1427 } catch (URISyntaxException e12) {
1428
1429 }
1430 }
1431
1432 receiversPanel.updateReceiverTreeInDispatchThread();
1433 }).start();
1434 }
1435 File saveConfigFile = receiverConfigurationPanel.getModel().getSaveConfigFile();
1436 if (saveConfigFile != null) {
1437 ReceiversHelper.getInstance().saveReceiverConfiguration(saveConfigFile);
1438 }
1439 });
1440
1441 receiverConfigurationPanel.setDialog(dialog);
1442 dialog.getContentPane().add(receiverConfigurationPanel);
1443
1444 dialog.pack();
1445
1446 Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
1447 dialog.setLocation(
1448 (screenSize.width / 2) - (dialog.getWidth() / 2),
1449 (screenSize.height / 2) - (dialog.getHeight() / 2));
1450
1451 dialog.setVisible(true);
1452 });
1453 }
1454
1455
1456
1457
1458 public boolean exit() {
1459 getSettingsManager().saveSettings();
1460
1461 return shutdown();
1462 }
1463
1464 void addWelcomePanel() {
1465 getTabbedPane().insertTab(
1466 ChainsawTabbedPane.WELCOME_TAB, new ImageIcon(ChainsawIcons.ABOUT), welcomePanel,
1467 "Welcome/Help", 0);
1468 getTabbedPane().setSelectedComponent(welcomePanel);
1469 getPanelMap().put(ChainsawTabbedPane.WELCOME_TAB, welcomePanel);
1470 }
1471
1472 void removeWelcomePanel() {
1473 EventQueue.invokeLater(() -> {
1474 if (getTabbedPane().containsWelcomePanel()) {
1475 getTabbedPane().remove(
1476 getTabbedPane().getComponentAt(getTabbedPane().indexOfTab(ChainsawTabbedPane.WELCOME_TAB)));
1477 }
1478 });
1479 }
1480
1481 ChainsawStatusBar getStatusBar() {
1482 return statusBar;
1483 }
1484
1485 public void showApplicationPreferences() {
1486 applicationPreferenceModelPanel.updateModel();
1487 preferencesFrame.setVisible(true);
1488 }
1489
1490 public void showReceiverConfiguration() {
1491 showReceiverConfigurationPanel();
1492 }
1493
1494 public void showAboutBox() {
1495 if (aboutBox == null) {
1496 aboutBox = new ChainsawAbout(this);
1497 }
1498
1499 aboutBox.setVisible(true);
1500 }
1501
1502 Map getPanels() {
1503 Map m = new HashMap();
1504 Set<Map.Entry<String, Component>> panelSet = getPanelMap().entrySet();
1505
1506 for (Object aPanelSet : panelSet) {
1507 Map.Entry entry = (Map.Entry) aPanelSet;
1508 Object o = entry.getValue();
1509 boolean valueToSend;
1510 valueToSend = !(o instanceof LogPanel) || ((DockablePanel) entry.getValue()).isDocked();
1511 m.put(entry.getKey(), valueToSend);
1512 }
1513
1514 return m;
1515 }
1516
1517 void displayPanel(String panelName, boolean display) {
1518 Component p = getPanelMap().get(panelName);
1519
1520 int index = getTabbedPane().indexOfTab(panelName);
1521
1522 if ((index == -1) && display) {
1523 getTabbedPane().addTab(panelName, p);
1524 }
1525
1526 if ((index > -1) && !display) {
1527 getTabbedPane().removeTabAt(index);
1528 }
1529 }
1530
1531
1532
1533
1534
1535 public boolean shutdown() {
1536 if (getApplicationPreferenceModel().isConfirmExit()) {
1537 if (
1538 JOptionPane.showConfirmDialog(
1539 LogUI.this, "Are you sure you want to exit Chainsaw?",
1540 "Confirm Exit", JOptionPane.YES_NO_OPTION,
1541 JOptionPane.INFORMATION_MESSAGE) != JOptionPane.YES_OPTION) {
1542 return false;
1543 }
1544
1545 }
1546
1547 final JWindow progressWindow = new JWindow();
1548 final ProgressPanel panel = new ProgressPanel(1, 3, "Shutting down");
1549 progressWindow.getContentPane().add(panel);
1550 progressWindow.pack();
1551
1552 Point p = new Point(getLocation());
1553 p.move((int) getSize().getWidth() >> 1, (int) getSize().getHeight() >> 1);
1554 progressWindow.setLocation(p);
1555 progressWindow.setVisible(true);
1556
1557 Runnable runnable =
1558 () -> {
1559 try {
1560 int progress = 1;
1561 final int delay = 25;
1562
1563 handler.close();
1564 panel.setProgress(progress++);
1565
1566 Thread.sleep(delay);
1567
1568 pluginRegistry.stopAllPlugins();
1569 panel.setProgress(progress++);
1570
1571 Thread.sleep(delay);
1572
1573 panel.setProgress(progress++);
1574 Thread.sleep(delay);
1575 } catch (Exception e) {
1576 e.printStackTrace();
1577 }
1578
1579 fireShutdownEvent();
1580 performShutdownAction();
1581 progressWindow.setVisible(false);
1582 };
1583
1584 if (OSXIntegration.IS_OSX) {
1585
1586
1587
1588
1589
1590 runnable.run();
1591 } else {
1592 new Thread(runnable).start();
1593 }
1594 return true;
1595 }
1596
1597
1598
1599
1600 private void fireShutdownEvent() {
1601 ShutdownListener[] listeners =
1602 shutdownListenerList.getListeners(
1603 ShutdownListener.class);
1604
1605 for (ShutdownListener listener : listeners) {
1606 listener.shuttingDown();
1607 }
1608 }
1609
1610
1611
1612
1613
1614
1615
1616
1617 public final void setShutdownAction(Action shutdownAction) {
1618 this.shutdownAction = shutdownAction;
1619 }
1620
1621
1622
1623
1624
1625 private void performShutdownAction() {
1626 MessageCenter.getInstance().getLogger().debug(
1627 "Calling the shutdown Action. Goodbye!");
1628
1629 shutdownAction.actionPerformed(
1630 new ActionEvent(this, ActionEvent.ACTION_PERFORMED, "Shutting Down"));
1631 }
1632
1633
1634
1635
1636
1637
1638 LogPanel getCurrentLogPanel() {
1639 Component selectedTab = getTabbedPane().getSelectedComponent();
1640
1641 if (selectedTab instanceof LogPanel) {
1642 return (LogPanel) selectedTab;
1643 }
1644
1645 return null;
1646 }
1647
1648
1649
1650
1651 private void setStatusBarVisible(final boolean visible) {
1652 MessageCenter.getInstance().getLogger().debug(
1653 "Setting StatusBar to " + visible);
1654 SwingUtilities.invokeLater(
1655 () -> statusBar.setVisible(visible));
1656 }
1657
1658 boolean isStatusBarVisible() {
1659 return statusBar.isVisible();
1660 }
1661
1662
1663
1664
1665
1666
1667 public String getActiveTabName() {
1668 int index = getTabbedPane().getSelectedIndex();
1669
1670 if (index == -1) {
1671 return null;
1672 } else {
1673 return getTabbedPane().getTitleAt(index);
1674 }
1675 }
1676
1677
1678
1679
1680
1681
1682
1683 public void showHelp(URL url) {
1684 ensureWelcomePanelVisible();
1685
1686 getWelcomePanel().setURL(url);
1687 }
1688
1689
1690
1691
1692
1693
1694 private WelcomePanel getWelcomePanel() {
1695 return welcomePanel;
1696 }
1697
1698
1699
1700
1701
1702
1703 public boolean isLogTreePanelVisible() {
1704 return getCurrentLogPanel() != null && getCurrentLogPanel().isLogTreeVisible();
1705
1706 }
1707
1708
1709
1710
1711
1712
1713 public Map<String, Component> getPanelMap() {
1714 return panelMap;
1715 }
1716
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726 public SettingsManager getSettingsManager() {
1727 return sm;
1728 }
1729
1730
1731
1732
1733
1734
1735 public List<String> getFilterableColumns() {
1736 return filterableColumns;
1737 }
1738
1739
1740
1741
1742
1743
1744 public void setToolBarAndMenus(ChainsawToolBarAndMenus tbms) {
1745 this.tbms = tbms;
1746 }
1747
1748
1749
1750
1751
1752
1753 public ChainsawToolBarAndMenus getToolBarAndMenus() {
1754 return tbms;
1755 }
1756
1757
1758
1759
1760
1761
1762 public Map getTableMap() {
1763 return tableMap;
1764 }
1765
1766
1767
1768
1769
1770
1771 public Map getTableModelMap() {
1772 return tableModelMap;
1773 }
1774
1775
1776
1777
1778
1779
1780 public void setTabbedPane(ChainsawTabbedPane tabbedPane) {
1781 this.tabbedPane = tabbedPane;
1782 }
1783
1784
1785
1786
1787
1788
1789 public ChainsawTabbedPane getTabbedPane() {
1790 return tabbedPane;
1791 }
1792
1793
1794
1795
1796 public final ApplicationPreferenceModel getApplicationPreferenceModel() {
1797 return applicationPreferenceModel;
1798 }
1799
1800
1801
1802
1803 public void setupTutorial() {
1804 SwingUtilities.invokeLater(
1805 () -> {
1806 Dimension screen = Toolkit.getDefaultToolkit().getScreenSize();
1807 setLocation(0, getLocation().y);
1808
1809 double chainsawwidth = 0.7;
1810 double tutorialwidth = 1 - chainsawwidth;
1811 setSize((int) (screen.width * chainsawwidth), getSize().height);
1812 invalidate();
1813 validate();
1814
1815 Dimension size = getSize();
1816 Point loc = getLocation();
1817 tutorialFrame.setSize(
1818 (int) (screen.width * tutorialwidth), size.height);
1819 tutorialFrame.setLocation(loc.x + size.width, loc.y);
1820 tutorialFrame.setVisible(true);
1821 });
1822 }
1823
1824 private void buildLogPanel(
1825 boolean customExpression, final String ident, final List<LoggingEvent> events)
1826 throws IllegalArgumentException {
1827 final LogPanel thisPanel = new LogPanel(getStatusBar(), ident, cyclicBufferSize, allColorizers, applicationPreferenceModel);
1828
1829 getSettingsManager().addSettingsListener(thisPanel);
1830 getSettingsManager().configure(thisPanel);
1831
1832
1833
1834
1835
1836
1837 if (customExpression) {
1838 handler.addCustomEventBatchListener(ident, thisPanel);
1839 } else {
1840 identifierPanels.add(thisPanel);
1841 handler.addEventBatchListener(thisPanel);
1842 }
1843
1844 TabIconHandler iconHandler = new TabIconHandler(ident);
1845 thisPanel.addEventCountListener(iconHandler);
1846
1847
1848 tabbedPane.addChangeListener(iconHandler);
1849
1850 PropertyChangeListener toolbarMenuUpdateListener =
1851 evt -> tbms.stateChange();
1852
1853 thisPanel.addPropertyChangeListener(toolbarMenuUpdateListener);
1854 thisPanel.addPreferencePropertyChangeListener(toolbarMenuUpdateListener);
1855
1856 thisPanel.addPropertyChangeListener(
1857 "docked",
1858 evt -> {
1859 LogPanel logPanel = (LogPanel) evt.getSource();
1860
1861 if (logPanel.isDocked()) {
1862 getPanelMap().put(logPanel.getIdentifier(), logPanel);
1863 getTabbedPane().addANewTab(
1864 logPanel.getIdentifier(), logPanel, null);
1865 getTabbedPane().setSelectedTab(getTabbedPane().indexOfTab(logPanel.getIdentifier()));
1866 } else {
1867 getTabbedPane().remove(logPanel);
1868 }
1869 });
1870
1871 logger.debug("adding logpanel to tabbed pane: " + ident);
1872
1873
1874
1875
1876 getTabbedPane().add(ident, thisPanel);
1877 getPanelMap().put(ident, thisPanel);
1878
1879
1880
1881
1882
1883 SwingUtilities.invokeLater(
1884 () -> {
1885 getTabbedPane().addANewTab(
1886 ident, thisPanel, new ImageIcon(ChainsawIcons.ANIM_RADIO_TOWER));
1887 thisPanel.layoutComponents();
1888 thisPanel.receiveEventBatch(ident, events);
1889 if (!getTabbedPane().tabSetting.isChainsawLog()) {
1890 displayPanel("chainsaw-log", false);
1891 }
1892 });
1893
1894 String msg = "added tab " + ident;
1895 MessageCenter.getInstance().getLogger().debug(msg);
1896 }
1897
1898
1899 public void createCustomExpressionLogPanel(String ident) {
1900
1901 try {
1902 List<LoggingEvent> list = new ArrayList<>();
1903 Rule rule = ExpressionRule.getRule(ident);
1904
1905 for (Object identifierPanel : identifierPanels) {
1906 LogPanel panel = (LogPanel) identifierPanel;
1907
1908 for (Object o : panel.getMatchingEvents(rule)) {
1909 LoggingEventWrapper e = (LoggingEventWrapper) o;
1910 list.add(e.getLoggingEvent());
1911 }
1912 }
1913
1914 buildLogPanel(true, ident, list);
1915 } catch (IllegalArgumentException iae) {
1916 MessageCenter.getInstance().getLogger().info(
1917 "Unable to add tab using expression: " + ident + ", reason: "
1918 + iae.getMessage());
1919 }
1920 }
1921
1922
1923
1924
1925
1926
1927
1928
1929 private void loadConfigurationUsingPluginClassLoader(final URL url) {
1930 ClassLoader classLoader = PluginClassLoaderFactory.getInstance().getClassLoader();
1931 ClassLoader previousTCCL = Thread.currentThread().getContextClassLoader();
1932
1933 if (url != null) {
1934 try {
1935
1936 Thread.currentThread().setContextClassLoader(classLoader);
1937 try {
1938 DOMConfigurator.configure(url);
1939 } catch (Exception e) {
1940 logger.warn("Unable to load configuration URL: " + url, e);
1941 }
1942 } finally {
1943
1944 Thread.currentThread().setContextClassLoader(previousTCCL);
1945 }
1946 }
1947 ensureChainsawAppenderHandlerAdded();
1948 }
1949
1950 private static void loadLookAndFeelUsingPluginClassLoader(String lookAndFeelClassName) {
1951 ClassLoader classLoader = PluginClassLoaderFactory.getInstance().getClassLoader();
1952 ClassLoader previousTCCL = Thread.currentThread().getContextClassLoader();
1953 try {
1954
1955 Thread.currentThread().setContextClassLoader(classLoader);
1956 UIManager.setLookAndFeel(lookAndFeelClassName);
1957 UIManager.getLookAndFeelDefaults().put("ClassLoader", classLoader);
1958 } catch (Exception e) {
1959 e.printStackTrace();
1960 } finally {
1961
1962 Thread.currentThread().setContextClassLoader(previousTCCL);
1963 }
1964 }
1965
1966
1967
1968
1969
1970 private void ensureChainsawAppenderHandlerAdded() {
1971 if (!LogManager.getLoggerRepository().getRootLogger().isAttached(handler)) {
1972 LogManager.getLoggerRepository().getRootLogger().addAppender(handler);
1973 }
1974 }
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984 private class NewTabEventBatchReceiver implements EventBatchListener {
1985
1986
1987
1988
1989
1990
1991 public void receiveEventBatch(
1992 final String ident, final List<LoggingEvent> events) {
1993 if (events.size() == 0) {
1994 return;
1995 }
1996
1997 if (!isGUIFullyInitialized) {
1998 synchronized (initializationLock) {
1999 while (!isGUIFullyInitialized) {
2000 System.out.println(
2001 "Wanting to add a row, but GUI not initialized, waiting...");
2002
2003
2004
2005
2006 try {
2007 initializationLock.wait(1000);
2008 logger.debug("waiting for initialization to complete");
2009 } catch (InterruptedException e) {
2010 }
2011 }
2012 logger.debug("out of system initialization wait loop");
2013 }
2014 }
2015
2016 if (!getPanelMap().containsKey(ident)) {
2017 logger.debug("panel " + ident + " does not exist - creating");
2018 try {
2019 buildLogPanel(false, ident, events);
2020 } catch (IllegalArgumentException iae) {
2021 logger.error("error creating log panel", iae);
2022
2023 }
2024 }
2025 }
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038 public String getInterestedIdentifier() {
2039
2040 return null;
2041 }
2042 }
2043
2044 private class TabIconHandler implements EventCountListener, ChangeListener {
2045
2046
2047 private boolean newEvents = true;
2048 private boolean seenEvents = false;
2049 private final String ident;
2050 ImageIcon NEW_EVENTS = new ImageIcon(ChainsawIcons.ANIM_RADIO_TOWER);
2051 ImageIcon HAS_EVENTS = new ImageIcon(ChainsawIcons.INFO);
2052 Icon SELECTED = LineIconFactory.createBlankIcon();
2053
2054 public TabIconHandler(String identifier) {
2055 ident = identifier;
2056
2057 new Thread(
2058 () -> {
2059 while (true) {
2060
2061
2062 if (getTabbedPane().indexOfTab(ident) > -1 &&
2063 getTabbedPane().getSelectedIndex() == getTabbedPane()
2064 .indexOfTab(ident)) {
2065 getTabbedPane().setIconAt(
2066 getTabbedPane().indexOfTab(ident), SELECTED);
2067 newEvents = false;
2068 seenEvents = true;
2069 } else if (getTabbedPane().indexOfTab(ident) > -1) {
2070 if (newEvents) {
2071 getTabbedPane().setIconAt(
2072 getTabbedPane().indexOfTab(ident), NEW_EVENTS);
2073 newEvents = false;
2074 seenEvents = false;
2075 } else if (!seenEvents) {
2076 getTabbedPane().setIconAt(
2077 getTabbedPane().indexOfTab(ident), HAS_EVENTS);
2078 }
2079 }
2080
2081 try {
2082 Thread.sleep(handler.getQueueInterval() + 1000);
2083 } catch (InterruptedException ie) {
2084 }
2085 }
2086 }).start();
2087 }
2088
2089
2090
2091
2092
2093
2094
2095 public void eventCountChanged(int currentCount, int totalCount) {
2096 newEvents = true;
2097 }
2098
2099 public void stateChanged(ChangeEvent event) {
2100 if (
2101 getTabbedPane().indexOfTab(ident) > -1 && getTabbedPane().indexOfTab(ident) == getTabbedPane().getSelectedIndex()) {
2102 getTabbedPane().setIconAt(getTabbedPane().indexOfTab(ident), SELECTED);
2103 }
2104 }
2105 }
2106 }