1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package net.sourceforge.buildmonitor;
17
18 import java.awt.CheckboxMenuItem;
19 import java.awt.Desktop;
20 import java.awt.Font;
21 import java.awt.Image;
22 import java.awt.Menu;
23 import java.awt.MenuItem;
24 import java.awt.PopupMenu;
25 import java.awt.SystemTray;
26 import java.awt.Toolkit;
27 import java.awt.TrayIcon;
28 import java.awt.TrayIcon.MessageType;
29 import java.awt.event.ActionEvent;
30 import java.awt.event.ActionListener;
31 import java.awt.event.ItemEvent;
32 import java.awt.event.ItemListener;
33 import java.io.IOException;
34 import java.net.URI;
35 import java.text.MessageFormat;
36 import java.text.SimpleDateFormat;
37 import java.util.ArrayList;
38 import java.util.Collections;
39 import java.util.Date;
40 import java.util.List;
41 import java.util.Locale;
42 import java.util.ResourceBundle;
43
44 import javax.swing.ImageIcon;
45 import javax.swing.JOptionPane;
46 import javax.swing.UIManager;
47
48 import net.sourceforge.buildmonitor.monitors.BambooMonitor;
49 import net.sourceforge.buildmonitor.monitors.Monitor;
50
51 import org.joda.time.LocalDateTime;
52 import org.joda.time.Period;
53
54
55
56
57
58
59 public class BuildMonitorImpl implements Runnable, BuildMonitor
60 {
61
62
63
64
65 private static final String MESSAGES_BASE_NAME = "messages/GUIStrings";
66
67 private static final String IMAGE_MONITORING_EXCEPTION = "images/network-offline.png";
68
69 private static final String IMAGE_INITIAL_ICON = "images/utilities-system-monitor.png";
70
71 private static final String IMAGE_ABOUT_ICON = "images/about.png";
72
73 private static final String IMAGE_BUILD_SUCCESS = "images/green_up.png";
74
75 private static final String IMAGE_BUILD_FAILURE = "images/red_down.png";
76
77
78 private static final Font SUCCESSFULL_BUILD_MENUITEM_FONT = new Font(Font.SANS_SERIF, Font.PLAIN, 12);
79
80
81 private static final Font FAILED_BUILD_MENUITEM_FONT = new Font(Font.SANS_SERIF, Font.BOLD, 14);
82
83 private static final int TOOLTIP_MAX_LENGTH = 127;
84
85 private static final String OPTIONS_RELATED_MESSAGES_SUFFIX = " Double click here to edit Options.";
86
87 private static final String TRUNCATED_MESSAGE_SUFFIX = " [...]";
88
89 private static final int SORT_BY_NAME = 1;
90
91 private static final int SORT_BY_AGE = 2;
92
93
94
95
96
97
98
99
100 private class OpenURIInBrowserActionListener implements ActionListener
101 {
102
103
104
105
106 private URI uri = null;
107
108
109
110
111
112
113
114
115
116 public OpenURIInBrowserActionListener(URI theURI)
117 {
118 this.uri = theURI;
119 }
120
121
122
123
124
125
126
127
128 public void actionPerformed(ActionEvent e)
129 {
130 if (Desktop.isDesktopSupported())
131 {
132 try
133 {
134 Desktop.getDesktop().browse(this.uri);
135 }
136 catch (IOException err)
137 {
138
139 }
140 }
141 }
142
143 }
144
145
146
147
148 private class ShutdownThread extends Thread
149 {
150 public void run()
151 {
152
153 if (monitor != null)
154 {
155 monitor.stop();
156 }
157 }
158 }
159
160
161
162
163
164
165
166
167 private class TrayIconUpdater implements Runnable
168 {
169 private Image newIcon;
170
171 private String iconTooltip;
172
173 private String messageToDisplay;
174
175 private String messageCaption;
176
177 private MessageType messageType;
178
179 private ActionListener trayIconNewActionListener;
180
181 public TrayIconUpdater(Image theNewIcon, String theNewIconTooltip, String theMessageCaption, String theMessageToDisplay, MessageType theMessageType, ActionListener theTrayIconNewActionListener)
182 {
183 this.newIcon = theNewIcon;
184 this.iconTooltip = theNewIconTooltip;
185 this.messageToDisplay = theMessageToDisplay;
186 this.messageCaption = theMessageCaption;
187 this.messageType = theMessageType;
188 this.trayIconNewActionListener = theTrayIconNewActionListener;
189 }
190
191 public void run()
192 {
193 if (this.iconTooltip != null)
194 {
195 trayIcon.setToolTip(this.iconTooltip);
196 }
197 if (this.newIcon != null)
198 {
199 trayIcon.setImage(this.newIcon);
200 }
201 if (this.messageToDisplay != null)
202 {
203 trayIcon.displayMessage(this.messageCaption, this.messageToDisplay, this.messageType);
204 }
205 if (this.trayIconNewActionListener != null)
206 {
207 ActionListener[] listeners = trayIcon.getActionListeners();
208 for (ActionListener listener : listeners)
209 {
210 trayIcon.removeActionListener(listener);
211 }
212 trayIcon.addActionListener(this.trayIconNewActionListener);
213 }
214 }
215
216 }
217
218
219
220
221
222
223
224
225
226 private class BuildStatusUpdater implements Runnable
227 {
228
229
230
231
232 List<BuildReport> listOfBuildReportsOrderedByName = null;
233 int numberOfFailedBuilds = 0;
234
235
236
237
238
239
240
241
242
243
244
245 public BuildStatusUpdater(List<BuildReport> theListOfBuildReportsOrderedByName)
246 {
247 this.listOfBuildReportsOrderedByName = theListOfBuildReportsOrderedByName;
248 }
249
250
251
252
253
254
255
256
257 public void run()
258 {
259 PopupMenu trayIconPopupMenu = trayIcon.getPopupMenu();
260
261
262 while (trayIconPopupMenu.getItemCount() > numberOfItemInEmptyTrayMenu)
263 {
264 trayIconPopupMenu.remove(indexOfTheFirstBuildResultMenuItem);
265 }
266
267
268 int newMenuItemIndex = indexOfTheFirstBuildResultMenuItem;
269 for (BuildReport buildReport : this.listOfBuildReportsOrderedByName)
270 {
271
272 MenuItem newMenuItem = createNewMenuItemForBuildReport(buildReport, FAILED_BUILD_MENUITEM_FONT, SUCCESSFULL_BUILD_MENUITEM_FONT);
273
274
275 trayIconPopupMenu.insert(newMenuItem, newMenuItemIndex);
276 newMenuItemIndex++;
277 }
278
279 trayIconPopupMenu.insertSeparator(newMenuItemIndex);
280
281
282 ActionListener[] listeners = trayIcon.getActionListeners();
283 for (ActionListener listener : listeners)
284 {
285 trayIcon.removeActionListener(listener);
286 }
287 trayIcon.addActionListener(openBuildServerHomePageActionListener);
288
289
290 if (this.numberOfFailedBuilds > 0)
291 {
292 trayIcon.setImage(buildFailureIcon);
293 }
294 else
295 {
296 trayIcon.setImage(buildSuccessIcon);
297 }
298 SimpleDateFormat timeFormat = new SimpleDateFormat("HH'h'mm");
299 trayIcon.setToolTip(monitor.getSystemTrayIconTooltipHeader() + "\nLast update at " + timeFormat.format(new Date()) + "\n" + this.numberOfFailedBuilds + " failed builds out of " + this.listOfBuildReportsOrderedByName.size());
300 }
301
302
303
304
305
306
307
308
309
310
311
312
313 private MenuItem createNewMenuItemForBuildReport(BuildReport theBuildReport, Font theBuildFailedFont, Font theBuildSucessFont)
314 {
315 MenuItem newMenuItem = new MenuItem(getMenuItemLabelForBuildReport(theBuildReport));
316 if (theBuildReport.hasFailed())
317 {
318 newMenuItem.setFont(theBuildFailedFont);
319 this.numberOfFailedBuilds++;
320 }
321 else
322 {
323 newMenuItem.setFont(theBuildSucessFont);
324 }
325 newMenuItem.setActionCommand(theBuildReport.getId());
326 newMenuItem.setName(theBuildReport.getName());
327 ActionListener newMenuItemActionListener = new ActionListener() {
328 public void actionPerformed(ActionEvent e)
329 {
330 if (Desktop.isDesktopSupported())
331 {
332 try
333 {
334 Desktop.getDesktop().browse(monitor.getBuildURI(e.getActionCommand()));
335 }
336 catch (IOException err)
337 {
338
339 }
340 }
341 }
342 };
343 newMenuItem.addActionListener(newMenuItemActionListener);
344 return newMenuItem;
345 }
346
347
348
349
350
351
352 private String getMenuItemLabelForBuildReport(BuildReport theBuildReport)
353 {
354 String howLongAgo = null;
355 Period ageOfTheBuild = new Period(new LocalDateTime(theBuildReport.getDate()), new LocalDateTime());
356
357 if (ageOfTheBuild.getYears() > 0)
358 {
359 if (ageOfTheBuild.getYears() > 1)
360 {
361 howLongAgo = ageOfTheBuild.getYears() + " years ago";
362 }
363 else
364 {
365 howLongAgo = "1 year ago";
366 }
367 }
368 else if (ageOfTheBuild.getMonths() > 0)
369 {
370 if (ageOfTheBuild.getMonths() > 1)
371 {
372 howLongAgo = ageOfTheBuild.getMonths() + " months ago";
373 }
374 else
375 {
376 howLongAgo = "1 month ago";
377 }
378 }
379 else if (ageOfTheBuild.getWeeks() > 0)
380 {
381 if (ageOfTheBuild.getWeeks() > 1)
382 {
383 howLongAgo = ageOfTheBuild.getWeeks() + " weeks ago";
384 }
385 else
386 {
387 howLongAgo = "1 week ago";
388 }
389 }
390 else if (ageOfTheBuild.getDays() > 0)
391 {
392 if (ageOfTheBuild.getDays() > 1)
393 {
394 howLongAgo = ageOfTheBuild.getDays() + " days ago";
395 }
396 else
397 {
398 howLongAgo = "yesterday";
399 }
400 }
401 else if (ageOfTheBuild.getHours() > 0)
402 {
403 if (ageOfTheBuild.getHours() > 1)
404 {
405 howLongAgo = ageOfTheBuild.getHours() + " hours ago";
406 }
407 else
408 {
409 howLongAgo = "one hour ago";
410 }
411 }
412 else if (ageOfTheBuild.getMinutes() > 5)
413 {
414 howLongAgo = ageOfTheBuild.getMinutes() + " minutes ago";
415 }
416 else if (ageOfTheBuild.getMinutes() > 1)
417 {
418 howLongAgo = "a few minutes ago";
419 }
420 else
421 {
422 howLongAgo = "a few seconds ago";
423 }
424 return theBuildReport.getName() + " (" + howLongAgo + ")";
425 }
426 }
427
428
429
430
431
432 private ResourceBundle messages = null;
433
434 private Monitor monitor = null;
435
436 private Thread monitorThread = null;
437
438 private TrayIcon trayIcon = null;
439
440 private Image initialIcon = null;
441
442 private Image buildSuccessIcon = null;
443
444 private Image buildFailureIcon = null;
445
446 private Image monitoringExceptionIcon = null;
447
448 private ImageIcon aboutIcon = null;
449
450 private String currentlyReportedMonitoringException = null;
451
452 private ActionListener openBuildServerHomePageActionListener = null;
453
454 private ActionListener openOptionsDialogActionListener = null;
455
456 private int currentSortOrder = SORT_BY_NAME;
457
458 private CheckboxMenuItem sortByNameMenuItem = null;
459
460 private CheckboxMenuItem sortByAgeMenuItem = null;
461
462
463
464
465
466 private int numberOfItemInEmptyTrayMenu = -1;
467
468
469
470
471
472 private int indexOfTheFirstBuildResultMenuItem = -1;
473
474
475
476
477 private List<BuildReport> previousBuildReports = new ArrayList<BuildReport>();
478
479
480
481
482
483
484
485
486 public void run()
487 {
488 try
489 {
490
491 this.messages = ResourceBundle.getBundle(MESSAGES_BASE_NAME, Locale.getDefault(), this.getClass().getClassLoader());
492
493
494 this.initialIcon = Toolkit.getDefaultToolkit().getImage(this.getClass().getClassLoader().getResource(IMAGE_INITIAL_ICON));
495 this.monitoringExceptionIcon = Toolkit.getDefaultToolkit().getImage(this.getClass().getClassLoader().getResource(IMAGE_MONITORING_EXCEPTION));
496 this.buildSuccessIcon = Toolkit.getDefaultToolkit().getImage(this.getClass().getClassLoader().getResource(IMAGE_BUILD_SUCCESS));
497 this.buildFailureIcon = Toolkit.getDefaultToolkit().getImage(this.getClass().getClassLoader().getResource(IMAGE_BUILD_FAILURE));
498 this.aboutIcon = new ImageIcon(Toolkit.getDefaultToolkit().getImage(this.getClass().getClassLoader().getResource(IMAGE_ABOUT_ICON)));
499
500
501 if (SystemTray.isSupported())
502 {
503
504 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
505
506
507 this.monitor = new BambooMonitor(this);
508 this.openBuildServerHomePageActionListener = new ActionListener()
509 {
510 public void actionPerformed(ActionEvent e)
511 {
512 if (Desktop.isDesktopSupported())
513 {
514 try
515 {
516 Desktop.getDesktop().browse(monitor.getMainPageURI());
517 }
518 catch (IOException err)
519 {
520
521 }
522 }
523 }
524 };
525
526
527
528
529 SystemTray tray = SystemTray.getSystemTray();
530
531
532 PopupMenu trayMenu = new PopupMenu();
533
534
535 MenuItem buildServerHomePageMenuItem = new MenuItem(this.monitor.getMonitoredBuildSystemName() + " " + getMessage(MESSAGEKEY_TRAYICON_MENUITEM_BUILD_SERVER_HOME_PAGE_SUFFIX));
536 buildServerHomePageMenuItem.addActionListener(this.openBuildServerHomePageActionListener);
537 trayMenu.add(buildServerHomePageMenuItem);
538
539
540 MenuItem updateStatusNowMenuItem = new MenuItem(getMessage(MESSAGEKEY_TRAYICON_MENUITEM_UPDATE_STATUS_NOW));
541 ActionListener updateStatusNowMenuItemActionListener = new ActionListener()
542 {
543 public void actionPerformed(ActionEvent e)
544 {
545 monitorThread.interrupt();
546 }
547 };
548 updateStatusNowMenuItem.addActionListener(updateStatusNowMenuItemActionListener);
549 trayMenu.add(updateStatusNowMenuItem);
550
551
552 Menu sortMenu = new Menu(getMessage(MESSAGEKEY_TRAYICON_MENU_SORT));
553 this.sortByAgeMenuItem = new CheckboxMenuItem(getMessage(MESSAGEKEY_TRAYICON_MENUITEM_SORT_BY_AGE), true);
554 this.currentSortOrder = SORT_BY_AGE;
555 sortMenu.add(this.sortByAgeMenuItem);
556 this.sortByNameMenuItem = new CheckboxMenuItem(getMessage(MESSAGEKEY_TRAYICON_MENUITEM_SORT_BY_NAME), false);
557 sortMenu.add(this.sortByNameMenuItem);
558 ItemListener sortByNameMenuItemActionListener = new ItemListener()
559 {
560 public void itemStateChanged(ItemEvent e)
561 {
562 if (e.getStateChange() == ItemEvent.SELECTED)
563 {
564 sortByNameMenuItem.setState(true);
565 sortByAgeMenuItem.setState(false);
566 currentSortOrder = SORT_BY_NAME;
567 reportConfigurationUpdatedToBeTakenIntoAccountImmediately();
568 }
569 else
570 {
571 sortByNameMenuItem.setState(true);
572 reportConfigurationUpdatedToBeTakenIntoAccountImmediately();
573 }
574
575 }
576 };
577 this.sortByNameMenuItem.addItemListener(sortByNameMenuItemActionListener);
578 ItemListener sortByAgeMenuItemActionListener = new ItemListener()
579 {
580 public void itemStateChanged(ItemEvent e)
581 {
582 if (e.getStateChange() == ItemEvent.SELECTED)
583 {
584 sortByNameMenuItem.setState(false);
585 sortByAgeMenuItem.setState(true);
586 currentSortOrder = SORT_BY_AGE;
587 reportConfigurationUpdatedToBeTakenIntoAccountImmediately();
588 }
589 else
590 {
591 sortByAgeMenuItem.setState(true);
592 reportConfigurationUpdatedToBeTakenIntoAccountImmediately();
593 }
594
595 }
596 };
597 this.sortByAgeMenuItem.addItemListener(sortByAgeMenuItemActionListener);
598 trayMenu.add(sortMenu);
599
600
601 MenuItem optionsMenuItem = new MenuItem(getMessage(MESSAGEKEY_TRAYICON_MENUITEM_OPTIONS));
602 this.openOptionsDialogActionListener = new ActionListener() {
603 public void actionPerformed(ActionEvent e)
604 {
605 try
606 {
607 monitor.displayOptionsDialog();
608 }
609 catch (Exception exc)
610 {
611 panic(exc);
612 }
613 }
614 };
615 optionsMenuItem.addActionListener(this.openOptionsDialogActionListener);
616 trayMenu.add(optionsMenuItem);
617
618
619 trayMenu.addSeparator();
620
621
622 this.indexOfTheFirstBuildResultMenuItem = trayMenu.getItemCount();
623
624
625 MenuItem aboutMenuItem = new MenuItem(getMessage(MESSAGEKEY_TRAYICON_MENUITEM_ABOUT));
626 ActionListener aboutMenuItemActionListener = new ActionListener()
627 {
628 public void actionPerformed(ActionEvent e)
629 {
630
631 JOptionPane.showMessageDialog(null, "This is the preview version of build monitor, by sbrunot@gmail.com.\nBuild Revision: unknown\nCurrent monitor is the Bamboo monitor.\n\n", "About...", JOptionPane.INFORMATION_MESSAGE, aboutIcon);
632 }
633 };
634 aboutMenuItem.addActionListener(aboutMenuItemActionListener);
635 trayMenu.add(aboutMenuItem);
636
637
638 Menu exitMenu = new Menu(getMessage(MESSAGEKEY_TRAYICON_MENU_EXIT));
639 MenuItem exitMenuItem = new MenuItem(getMessage(MESSAGEKEY_TRAYICON_MENUITEM_EXIT));
640 ActionListener exitMenuItemActionListener = new ActionListener() {
641 public void actionPerformed(ActionEvent e)
642 {
643 System.exit(0);
644 }
645 };
646 exitMenuItem.addActionListener(exitMenuItemActionListener);
647 exitMenu.add(exitMenuItem);
648 trayMenu.add(exitMenu);
649
650 this.numberOfItemInEmptyTrayMenu = trayMenu.getItemCount();
651
652 this.trayIcon = new TrayIcon(this.initialIcon, getMessage(MESSAGEKEY_TRAYICON_INITIAL_TOOLTIP), trayMenu);
653 tray.add(trayIcon);
654 }
655 else
656 {
657 panic(getMessage(MESSAGEKEY_ERROR_SYSTEMTRAY_NOT_SUPPORTED));
658 }
659
660
661 Runtime.getRuntime().addShutdownHook(new ShutdownThread());
662
663
664 this.monitorThread = new Thread(this.monitor, "Bamboo monitor thread");
665 this.monitorThread.start();
666
667 this.trayIcon.addActionListener(openBuildServerHomePageActionListener);
668
669 }
670 catch(Throwable t)
671 {
672 panic(t);
673 }
674 }
675
676
677
678
679
680
681
682
683 public void panic(String theErrorMessage)
684 {
685 showErrorMessage(theErrorMessage);
686
687 System.exit(1);
688 }
689
690
691
692
693 public void panic(Throwable theUnexpectedError)
694 {
695 MessageFormat errorMessage = new MessageFormat(getMessage(MESSAGEKEY_UNEXPECTED_ERROR_MESSAGE));
696 panic(errorMessage.format(new Object[] {theUnexpectedError.getMessage(), getStackTrace(theUnexpectedError)}));
697 }
698
699
700
701
702 public String getMessage(String theMessageKey)
703 {
704 return this.messages.getString(theMessageKey);
705 }
706
707
708
709
710 public Image getDialogsDefaultIcon()
711 {
712 return this.initialIcon;
713 }
714
715
716
717
718 public void reportMonitoringException(MonitoringException theMonitoringException)
719 {
720
721 if ((this.currentlyReportedMonitoringException == null) || (!this.currentlyReportedMonitoringException.equals(theMonitoringException.getMessage())))
722 {
723
724 String messageToDisplayInAlertBubble = theMonitoringException.getMessage();
725 String tooltipMessage = theMonitoringException.getMessage();
726
727 ActionListener trayIconNewActionListener = this.openBuildServerHomePageActionListener;
728
729 if (theMonitoringException.isOptionsRelated())
730 {
731
732
733 messageToDisplayInAlertBubble += OPTIONS_RELATED_MESSAGES_SUFFIX;
734
735 if (tooltipMessage != null && (tooltipMessage.length() + OPTIONS_RELATED_MESSAGES_SUFFIX.length()) > TOOLTIP_MAX_LENGTH)
736 {
737 tooltipMessage = tooltipMessage.substring(0, TOOLTIP_MAX_LENGTH - TRUNCATED_MESSAGE_SUFFIX.length() - OPTIONS_RELATED_MESSAGES_SUFFIX.length() - 1) + TRUNCATED_MESSAGE_SUFFIX + OPTIONS_RELATED_MESSAGES_SUFFIX;
738 }
739 else if (tooltipMessage != null)
740 {
741 tooltipMessage += OPTIONS_RELATED_MESSAGES_SUFFIX;
742 }
743
744 trayIconNewActionListener = this.openOptionsDialogActionListener;
745 }
746 else
747 {
748
749 if (tooltipMessage != null && tooltipMessage.length() > TOOLTIP_MAX_LENGTH)
750 {
751 tooltipMessage = tooltipMessage.substring(0, TOOLTIP_MAX_LENGTH - TRUNCATED_MESSAGE_SUFFIX.length() - 1) + TRUNCATED_MESSAGE_SUFFIX;
752 }
753
754 if (theMonitoringException.getRelatedURI() != null)
755 {
756 trayIconNewActionListener = new OpenURIInBrowserActionListener(theMonitoringException.getRelatedURI());
757 }
758 }
759 javax.swing.SwingUtilities.invokeLater(new TrayIconUpdater(this.monitoringExceptionIcon, tooltipMessage, "Build Monitor need your attention", messageToDisplayInAlertBubble, MessageType.ERROR, trayIconNewActionListener));
760 this.currentlyReportedMonitoringException = theMonitoringException.getMessage();
761 }
762 }
763
764
765
766
767 public void reportConfigurationUpdatedToBeTakenIntoAccountImmediately()
768 {
769
770 if (this.monitorThread != null)
771 {
772 this.monitorThread.interrupt();
773 }
774 }
775
776
777
778
779
780 public void updateBuildStatus(List<BuildReport> theBuildsStatus)
781 {
782
783
784 List<BuildReport> buildsStatus = new ArrayList<BuildReport>(theBuildsStatus);
785 if (this.currentSortOrder == SORT_BY_NAME)
786 {
787 Collections.sort(buildsStatus, new BuildReport.NameComparator());
788 }
789 else if (this.currentSortOrder == SORT_BY_AGE)
790 {
791 Collections.sort(buildsStatus, new BuildReport.AgeComparator());
792 }
793
794
795 BuildStatusUpdater updater = new BuildStatusUpdater(buildsStatus);
796 javax.swing.SwingUtilities.invokeLater(updater);
797
798
799 this.currentlyReportedMonitoringException = null;
800
801
802 StringBuffer newFailingBuilds = new StringBuffer();
803 StringBuffer fixedBuilds = new StringBuffer();
804 for (BuildReport currentBuildReport : theBuildsStatus)
805 {
806 for (BuildReport previousBuildReport : this.previousBuildReports)
807 {
808 if (previousBuildReport.getId().equals(currentBuildReport.getId()))
809 {
810 if (previousBuildReport.getStatus() != currentBuildReport.getStatus())
811 {
812 if (currentBuildReport.getStatus() == BuildReport.Status.OK)
813 {
814 fixedBuilds.append(currentBuildReport.getName() + " is fixed.\n");
815 }
816 else
817 {
818 newFailingBuilds.append(currentBuildReport.getName() + " is failing.\n");
819 }
820 }
821 }
822 }
823 }
824 if ((newFailingBuilds.length() > 0) || (fixedBuilds.length() > 0))
825 {
826 MessageType messageType = MessageType.INFO;
827 if (newFailingBuilds.length() > 0)
828 {
829 messageType = MessageType.WARNING;
830 }
831 javax.swing.SwingUtilities.invokeLater(new TrayIconUpdater(null, null, "Build situation have changed !", newFailingBuilds.toString() + fixedBuilds.toString() + "Right click the tray icon to display the detailed build status.", messageType, null));
832 }
833 this.previousBuildReports = buildsStatus;
834 }
835
836
837
838
839
840
841 protected void showErrorMessage(String theErrorMessage)
842 {
843 if (this.messages != null)
844 {
845 JOptionPane.showMessageDialog(null, theErrorMessage, getMessage(MESSAGEKEY_ERROR_DIALOG_TITLE), JOptionPane.ERROR_MESSAGE);
846 }
847 else
848 {
849 JOptionPane.showMessageDialog(null, theErrorMessage, "Arghhhhhhhhh !", JOptionPane.ERROR_MESSAGE);
850 }
851 }
852
853
854
855
856
857
858 protected String getStackTrace(Throwable theThrowable)
859 {
860 StringBuffer buffer = new StringBuffer();
861 StackTraceElement[] stackElements = theThrowable.getStackTrace();
862 for (int i=0; i < stackElements.length; i++)
863 {
864 buffer.append(stackElements[i] + "\n");
865 }
866 return buffer.toString();
867 }
868
869 }