Hello guys,
the course plan of my university sometimes changes without any notification to the students. We often do not realize the change until it is too late, so I made this little notifier. It is intended to run once at startup. The message dialog only pops up if the plan has been changed, because it shall not annoy unnecessarily.
You just have to modify the url to make it work for your purpose. The page's md5 checksum is saved in the application data directory. Since that directory differs between OS, I check first whether Windows is used or Linux. If the md5 checksum is different to the one saved last time, it will notify you.
If you find any bugs, please tell me. Java 7 is required.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JOptionPane;
/**
*
* @author Deque
*
* Notifies via message dialog if the course plan has been updated.
*
* Tested on Arch Linux, Windows 7
*
*/
public class CoursePlanUpdateNotifier {
// URL to the course plan
private static final String PLAN_URL = "http://example.com";
// name of the file that contains the checksum of the last update
private static final String FILE_NAME = "course_date.txt";
private File file;
public static void main(String[] args) {
CoursePlanUpdateNotifier update = new CoursePlanUpdateNotifier();
if (update.planIsUpdated()) {
System.out.println("course plan has been updated");
JOptionPane.showMessageDialog(null, "course plan has been updated");
} else {
System.out.println("course plan has not changed");
}
}
public CoursePlanUpdateNotifier() {
prepareAppDataDir();
}
/**
* Prepares application data directory depending on OS.
*/
private void prepareAppDataDir() {
File appDataDir;
if (System.getProperty("os.name").toLowerCase().contains("windows")
&& new File(System.getProperty("user.home"), "AppData\\Roaming")
.exists()) {
appDataDir = new File(System.getProperty("user.home"),
"AppData\\Roaming\\CoursePlanUpdater");
} else {
appDataDir = new File(System.getProperty("user.home"),
".coursePlanUpdater");
}
createDir(appDataDir);
file = new File(appDataDir.getAbsolutePath() + "/" + FILE_NAME);
}
/**
* Creates directory if it doesn't exist.
*
* @param dir
* directory to be created
*/
private void createDir(File dir) {
if (!dir.exists()) {
if (!dir.mkdir()) {
System.err.println("error creating directory "
+ dir.getAbsolutePath());
JOptionPane.showMessageDialog(null, "error creating directory "
+ dir.getAbsolutePath(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
}
/**
*
* @return true, if plan has been updated, false otherwise
*/
public boolean planIsUpdated() {
Byte[] savedChecksum = getSavedChecksum();
byte[] currentChecksum = getChecksumFromURL();
boolean same = false;
if (savedChecksum != null
&& savedChecksum.length == currentChecksum.length) {
same = true;
for (int i = 0; i < currentChecksum.length; i++) {
if (currentChecksum[i] != savedChecksum[i]) {
same = false;
}
}
}
if (savedChecksum == null || !same) {
updateSavedChecksum(currentChecksum);
return true;
}
return false;
}
/**
* Saves given checksum in file
*
* @param checksum
*/
private void updateSavedChecksum(byte[] checksum) {
try (FileOutputStream fos = new FileOutputStream(file)) {
fos.write(checksum);
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(null,
"error saving file " + file.getAbsolutePath(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
/**
*
* @return checksum that is saved in file
*/
private Byte[] getSavedChecksum() {
List<Byte> byteList = new ArrayList<Byte>();
if (file.exists()) {
try (FileInputStream fin = new FileInputStream(file)) {
int nextByte = 0;
while ((nextByte = fin.read()) != -1) {
byteList.add((byte) nextByte);
}
} catch (IOException e) {
e.printStackTrace();
JOptionPane.showMessageDialog(
null,
"error getting saved date from file "
+ file.getAbsolutePath(), "Error",
JOptionPane.ERROR_MESSAGE);
}
}
return byteList.toArray(new Byte[byteList.size()]);
}
/**
*
* @return checksum of the given PLAN_URL
*/
private byte[] getChecksumFromURL() {
StringBuilder buff = new StringBuilder();
try {
URL url = new URL(PLAN_URL);
URLConnection urlc = url.openConnection();
urlc.addRequestProperty("user-agent", "Firefox");
try (BufferedReader in = new BufferedReader(new InputStreamReader(
urlc.getInputStream()))) {
String inputLine;
while ((inputLine = in.readLine()) != null) {
buff.append(inputLine);
}
}
} catch (IOException e) {
JOptionPane.showMessageDialog(null,
"error getting checksum from website " + PLAN_URL, "Error",
JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
return getChecksum(buff.toString());
}
/**
*
* @param string
* @return md5 checksum for the given string
*/
private static byte[] getChecksum(String string) {
byte[] bytes = string.getBytes();
MessageDigest digest;
try {
digest = MessageDigest.getInstance("MD5");
digest.update(bytes, 0, bytes.length);
return digest.digest();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
return null;
}
}