1 package com.github.sbugat.rundeckmonitor;
2
3 import java.awt.Desktop;
4 import java.awt.Image;
5 import java.awt.SystemTray;
6 import java.awt.Toolkit;
7 import java.awt.TrayIcon;
8 import java.awt.event.ActionEvent;
9 import java.awt.event.ActionListener;
10 import java.awt.event.WindowEvent;
11 import java.awt.event.WindowFocusListener;
12 import java.io.IOException;
13 import java.io.PrintWriter;
14 import java.io.StringWriter;
15 import java.net.URI;
16 import java.net.URISyntaxException;
17 import java.util.HashSet;
18 import java.util.List;
19 import java.util.Set;
20
21 import javax.swing.Icon;
22 import javax.swing.ImageIcon;
23 import javax.swing.JDialog;
24 import javax.swing.JOptionPane;
25 import javax.swing.UIManager;
26 import javax.swing.UnsupportedLookAndFeelException;
27
28 import org.slf4j.ext.XLogger;
29 import org.slf4j.ext.XLoggerFactory;
30
31 import com.github.sbugat.rundeckmonitor.configuration.RundeckMonitorConfiguration;
32 import com.github.sbugat.rundeckmonitor.tools.SystemTools;
33 import com.github.sbugat.rundeckmonitor.wizard.JobTabRedirection;
34 import com.github.sbugat.rundeckmonitor.wizard.RundeckMonitorConfigurationWizard;
35
36
37
38
39
40
41
42 public abstract class RundeckMonitorTrayIcon {
43
44
45 private static final XLogger LOG = XLoggerFactory.getXLogger(RundeckMonitor.class);
46
47
48 static final String RUNDECK_JOB_EXECUTION_URL = "/execution/";
49
50
51 static final String RUNDECK_MONITOR_PROJECT_URL = "https://sylvain-bugat.github.com/RundeckMonitor"; //$NON-NLS-1$
52
53
54 static final String LONG_EXECUTION_MARKER = " - LONG EXECUTION";
55
56
57 static final String NEW_FAILED_JOB_ALERT = "New failed job";
58
59
60 static final String NEW_LONG_EXECUTION_ALERT = "New long execution";
61
62
63 static final Image IMAGE_OK = Toolkit.getDefaultToolkit().getImage(RundeckMonitorTrayIcon.class.getClassLoader().getResource("OK.png"));
64
65 private static final Image IMAGE_LATE = Toolkit.getDefaultToolkit().getImage(RundeckMonitorTrayIcon.class.getClassLoader().getResource("LATE.png"));
66 static final Icon ICON_LATE_SMALL = new ImageIcon(Toolkit.getDefaultToolkit().getImage(RundeckMonitorTrayIcon.class.getClassLoader().getResource("LATE_SMALL.png")));
67
68 private static final Image IMAGE_KO = Toolkit.getDefaultToolkit().getImage(RundeckMonitorTrayIcon.class.getClassLoader().getResource("KO.png"));
69 static final Icon ICON_KO_SMALL = new ImageIcon(Toolkit.getDefaultToolkit().getImage(RundeckMonitorTrayIcon.class.getClassLoader().getResource("KO_SMALL.png")));
70
71 private static final Image IMAGE_KO_LATE = Toolkit.getDefaultToolkit().getImage(RundeckMonitorTrayIcon.class.getClassLoader().getResource("KO_LATE.png"));
72
73 private static final Image IMAGE_DISCONNECTED = Toolkit.getDefaultToolkit().getImage(RundeckMonitorTrayIcon.class.getClassLoader().getResource("DISCONNECTED.png"));
74
75
76 final SystemTray tray;
77
78
79 TrayIcon trayIcon;
80
81
82 final Desktop desktop;
83
84
85 ActionListener menuListener;
86
87
88 final ActionListener configurationListener;
89
90
91 final ActionListener aboutListener;
92
93
94 final ActionListener exitListener;
95
96
97 JDialog hiddenDialog;
98
99
100 final RundeckMonitorConfiguration rundeckMonitorConfiguration;
101
102
103 final RundeckMonitorState rundeckMonitorState;
104
105
106 final Set<Long> newLateProcess = new HashSet<>();
107
108
109 final Set<Long> newFailedProcess = new HashSet<>();
110
111
112
113
114
115
116
117 public RundeckMonitorTrayIcon(final RundeckMonitorConfiguration rundeckMonitorConfigurationArg, final RundeckMonitorState rundeckMonitorStateArg) {
118
119 LOG.entry(rundeckMonitorConfigurationArg, rundeckMonitorStateArg);
120
121 rundeckMonitorConfiguration = rundeckMonitorConfigurationArg;
122 rundeckMonitorState = rundeckMonitorStateArg;
123
124 if (SystemTray.isSupported()) {
125
126
127 try {
128 UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
129 }
130 catch (final ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
131
132
133 LOG.warn("Unsupported System Look&Feel", e);
134 }
135
136
137 desktop = Desktop.getDesktop();
138
139
140 configurationListener = new ActionListener() {
141
142 @Override
143 @SuppressWarnings("synthetic-access")
144 public void actionPerformed(final ActionEvent e) {
145 new RundeckMonitorConfigurationWizard(new RundeckMonitorConfiguration(rundeckMonitorConfiguration), false);
146 }
147 };
148
149
150 aboutListener = new ActionListener() {
151
152 @Override
153 @SuppressWarnings("synthetic-access")
154 public void actionPerformed(final ActionEvent e) {
155
156 try {
157 final URI executionURI = new URI(RUNDECK_MONITOR_PROJECT_URL);
158 desktop.browse(executionURI);
159 }
160 catch (final URISyntaxException | IOException exception) {
161
162 final StringWriter stringWriter = new StringWriter();
163 exception.printStackTrace(new PrintWriter(stringWriter));
164 JOptionPane.showMessageDialog(null, exception.getMessage() + System.lineSeparator() + stringWriter.toString(), "RundeckMonitor redirection error", JOptionPane.ERROR_MESSAGE);
165 }
166 }
167 };
168
169
170 tray = SystemTray.getSystemTray();
171
172
173 exitListener = new ActionListener() {
174
175 @Override
176 @SuppressWarnings("synthetic-access")
177 public void actionPerformed(final ActionEvent e) {
178 tray.remove(trayIcon);
179 SystemTools.exit(SystemTools.EXIT_CODE_OK);
180 }
181 };
182
183 hiddenDialog = new JDialog();
184 hiddenDialog.setSize(10, 10);
185
186 hiddenDialog.addWindowFocusListener(new WindowFocusListener() {
187
188 @Override
189 public void windowLostFocus(final WindowEvent e) {
190 hiddenDialog.setVisible(false);
191 }
192
193 @Override
194 public void windowGainedFocus(final WindowEvent e) {
195
196 }
197 });
198 }
199 else {
200
201 tray = null;
202 desktop = null;
203 configurationListener = null;
204 aboutListener = null;
205 exitListener = null;
206
207 JOptionPane.showMessageDialog(null, "SystemTray cannot be initialized", "RundeckMonitor initialization error", JOptionPane.ERROR_MESSAGE);
208
209 SystemTools.exit(SystemTools.EXIT_CODE_TRAY_ICON_UNSUPPORTED);
210 }
211 }
212
213
214
215
216
217
218 public abstract void updateExecutionIdsList(final List<JobExecutionInfo> listJobExecutionInfo);
219
220
221
222
223 public final void updateTrayIcon() {
224
225 LOG.entry();
226
227 if (rundeckMonitorState.isDisconnected()) {
228 trayIcon.setImage(IMAGE_DISCONNECTED);
229 }
230 else if (rundeckMonitorState.isFailedJobs()) {
231
232 if (rundeckMonitorState.isLateJobs()) {
233 trayIcon.setImage(IMAGE_KO_LATE);
234 }
235 else {
236 trayIcon.setImage(IMAGE_KO);
237 }
238 }
239 else if (rundeckMonitorState.isLateJobs()) {
240 trayIcon.setImage(IMAGE_LATE);
241 }
242 else {
243 trayIcon.setImage(IMAGE_OK);
244 }
245
246 LOG.exit();
247 }
248
249
250
251
252 public void reloadConfiguration() {
253
254 LOG.entry();
255
256 newLateProcess.clear();
257 newFailedProcess.clear();
258
259 trayIcon.setToolTip(rundeckMonitorConfiguration.getRundeckMonitorName());
260
261 LOG.exit();
262 }
263
264
265
266
267 public final void disposeTrayIcon() {
268
269 LOG.entry();
270 tray.remove(trayIcon);
271 LOG.exit();
272 }
273
274
275
276
277
278
279 final void openBrowser(final JobExecutionInfo jobExecutionInfo) {
280
281 LOG.entry();
282 final JobTabRedirection jobTabRedirection;
283
284 if (jobExecutionInfo.isLongExecution()) {
285 jobTabRedirection = JobTabRedirection.SUMMARY;
286 }
287 else {
288 jobTabRedirection = JobTabRedirection.valueOf(rundeckMonitorConfiguration.getJobTabRedirection());
289 }
290
291 try {
292 final String uRI = rundeckMonitorConfiguration.getRundeckUrl() + RUNDECK_JOB_EXECUTION_URL + jobTabRedirection.getAccessUrlPrefix() + '/' + jobExecutionInfo.getExecutionId() + jobTabRedirection.getAccessUrlSuffix();
293 LOG.info("Open execution with URL: {}", uRI);
294 final URI executionURI = new URI(uRI);
295 desktop.browse(executionURI);
296 }
297 catch (final URISyntaxException | IOException exception) {
298
299 final StringWriter stringWriter = new StringWriter();
300 exception.printStackTrace(new PrintWriter(stringWriter));
301 JOptionPane.showMessageDialog(null, exception.getMessage() + System.lineSeparator() + stringWriter.toString(), "RundeckMonitor redirection error", JOptionPane.ERROR_MESSAGE);
302 }
303
304 LOG.exit();
305 }
306 }