Last active
March 1, 2016 06:12
-
-
Save argius/3b272409f481fed3b1d8 to your computer and use it in GitHub Desktop.
ネットワークが切断されたことをアラームで知らせるツール.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.AWTException; | |
import java.awt.Image; | |
import java.awt.MenuItem; | |
import java.awt.PopupMenu; | |
import java.awt.SystemTray; | |
import java.awt.TrayIcon; | |
import java.awt.event.ActionEvent; | |
import java.awt.event.ActionListener; | |
import java.io.File; | |
import java.io.IOException; | |
import java.io.InputStream; | |
import java.net.HttpURLConnection; | |
import java.net.URL; | |
import java.util.Arrays; | |
import java.util.Date; | |
import java.util.concurrent.ExecutionException; | |
import java.util.concurrent.Executors; | |
import java.util.concurrent.ScheduledExecutorService; | |
import java.util.concurrent.ScheduledFuture; | |
import java.util.concurrent.TimeUnit; | |
import java.util.concurrent.atomic.AtomicBoolean; | |
import javax.sound.sampled.AudioFormat; | |
import javax.sound.sampled.AudioInputStream; | |
import javax.sound.sampled.AudioSystem; | |
import javax.sound.sampled.Clip; | |
import javax.sound.sampled.DataLine; | |
import javax.sound.sampled.LineUnavailableException; | |
import javax.sound.sampled.UnsupportedAudioFileException; | |
import javax.swing.ImageIcon; | |
import javax.swing.JOptionPane; | |
import javax.swing.SwingUtilities; | |
public final class NetworkAvailableChecker { | |
static final String title = "ネットワーク死活監視"; | |
static final String urlString = "..."; // TODO ファイルのURLを設定 | |
static final byte[] expectedFileContent = "argius".getBytes(); // TODO ファイルの内容を設定 | |
static final int expectedFileLength = expectedFileContent.length; | |
final AtomicBoolean suspend = new AtomicBoolean(false); | |
NetworkAvailableChecker() { | |
if (!SystemTray.isSupported()) { | |
throw new UnsupportedOperationException("プラットフォームがシステムトレイに対応していません"); | |
} | |
SystemTray tray = SystemTray.getSystemTray(); | |
Image image1 = new ImageIcon(getClass().getResource("icon.png")).getImage(); | |
Image image2 = new ImageIcon(getClass().getResource("icon2.png")).getImage(); | |
TrayIcon icon = new TrayIcon(image1, title); | |
icon.setPopupMenu(buildPopupMenu(icon, image1, image2)); | |
try { | |
tray.add(icon); | |
} catch (AWTException e) { | |
throw new IllegalStateException("タスクトレイにアイコンが追加できませんでした", e); | |
} | |
} | |
PopupMenu buildPopupMenu(final TrayIcon icon, Image image1, Image image2) { | |
PopupMenu popup = new PopupMenu(); | |
final MenuItem suspendItem = new MenuItem("保留"); | |
suspendItem.addActionListener(new ActionListener() { | |
@Override | |
public void actionPerformed(ActionEvent e) { | |
String oldLabel = suspendItem.getLabel(); | |
boolean state = suspend.get(); | |
String newLabel = state | |
? "保留" | |
: "再開"; | |
String tooltip = state | |
? title | |
: title + "[保留]"; | |
Image image = state | |
? image1 | |
: image2; | |
suspend.compareAndSet(state, !state); | |
suspendItem.setLabel(newLabel); | |
icon.setToolTip(tooltip); | |
icon.setImage(image); | |
System.out.printf("%s: [%s]が実行された%n", new Date(), oldLabel); | |
} | |
}); | |
MenuItem exitItem = new MenuItem("終了"); | |
exitItem.addActionListener(new ActionListener() { | |
@Override | |
public void actionPerformed(ActionEvent e) { | |
System.out.printf("%s: 終了が実行された%n", new Date()); | |
exitApp(); | |
} | |
}); | |
popup.add(suspendItem); | |
popup.add(exitItem); | |
return popup; | |
} | |
void exitApp() { | |
System.exit(0); | |
} | |
void runChecker() { | |
/* | |
* このメソッドはイベントディスパッチスレッドで実行しないこと | |
*/ | |
// システムプロパティーを読み込む | |
final int intervalSeconds = Integer.getInteger("NetworkAvailableChecker.interval", 15); | |
System.out.println("intervalSeconds: " + intervalSeconds); | |
Runnable task = new Runnable() { | |
@Override | |
public void run() { | |
if (suspend.get()) { | |
return; // 保留中なら何もしないで抜ける | |
} | |
try { | |
boolean ok = tryToAccessInternetFile(); | |
System.out.printf("%s: check = %s%n", new Date(), ok); | |
if (!ok) { | |
soundAlarm(); | |
} | |
} catch (Exception e) { | |
e.printStackTrace(); | |
exitApp(); | |
} | |
} | |
}; | |
ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(); | |
ScheduledFuture<?> future = scheduler.scheduleAtFixedRate(task, 0, intervalSeconds, TimeUnit.SECONDS); | |
try { | |
future.get(); | |
} catch (InterruptedException | ExecutionException e) { | |
throw new RuntimeException(e); | |
} | |
} | |
/** | |
* インターネット上の所定のファイルにアクセスを試みる。 | |
* @return 正常にアクセスできた場合は <code>true</code>、そうでなければ <code>false</code> | |
*/ | |
static boolean tryToAccessInternetFile() { | |
try { | |
URL url = new URL(urlString); // throws MalformedURLException | |
HttpURLConnection conn = (HttpURLConnection)url.openConnection(); | |
int status = conn.getResponseCode(); | |
if (status == 200) { | |
try (InputStream is = conn.getInputStream()) { | |
byte[] bytes = new byte[expectedFileLength]; | |
if (is.read(bytes) == expectedFileLength && Arrays.equals(bytes, expectedFileContent)) { | |
return true; // 正常 | |
} | |
else { | |
// 異常(想定外) | |
System.err.println("file content mismatch"); | |
} | |
} | |
} | |
else { | |
// 異常(想定外) | |
System.err.println("unexpected response status: " + status); | |
} | |
} catch (IOException e) { | |
// 異常(おそらくネットワーク切断) | |
e.printStackTrace(); | |
} | |
return false; | |
} | |
/** | |
* アラームを鳴らす。 | |
* @throws Exception 例外 | |
*/ | |
static void soundAlarm() throws Exception { | |
File file = new File("./alarm.wav"); | |
AudioInputStream ais; | |
try { | |
ais = AudioSystem.getAudioInputStream(file); | |
} catch (UnsupportedAudioFileException e) { | |
throw e; | |
} catch (IOException e) { | |
throw e; | |
} | |
AudioFormat format = ais.getFormat(); | |
DataLine.Info info = new DataLine.Info(Clip.class, format); | |
try (Clip line = (Clip)AudioSystem.getLine(info)) { | |
line.open(ais); | |
ais.close(); | |
line.start(); | |
while (!line.isRunning()) { | |
Thread.sleep(100L); // throws InterruptedException | |
} | |
while (line.isRunning()) { | |
Thread.sleep(100L); // throws InterruptedException | |
} | |
line.drain(); | |
} catch (LineUnavailableException e) { | |
throw e; | |
} catch (IOException e) { | |
throw e; | |
} | |
} | |
public static void main(String[] args) { | |
SwingUtilities.invokeLater(new Runnable() { | |
public void run() { | |
try { | |
final NetworkAvailableChecker o = new NetworkAvailableChecker(); | |
Executors.newSingleThreadExecutor().execute(new Runnable() { | |
@Override | |
public void run() { | |
o.runChecker(); | |
} | |
}); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
JOptionPane.showMessageDialog(null, e.getMessage()); | |
} | |
} | |
}); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment