Skip to content

Instantly share code, notes, and snippets.

@argius
Last active March 1, 2016 06:12
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save argius/3b272409f481fed3b1d8 to your computer and use it in GitHub Desktop.
Save argius/3b272409f481fed3b1d8 to your computer and use it in GitHub Desktop.
ネットワークが切断されたことをアラームで知らせるツール.java
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