package javacodebook.thread.crontab; /** * Ein auszuführendes Kommando. Wahlweise mit oder ohne Parametern. */ public interface Command { public void execute() throws Exception; public void execute(java.util.Hashtable parameter) throws Exception; } --- Neue Klasse --- package javacodebook.thread.crontab; import java.util.Date; import java.util.Enumeration; /** * Der CronDaemon startet zu jeder vollen Stunde und sieht in der Crontab * nach, ob ein oder mehrere Jobs zu erledigen sind. Ist dies der Fall, führt * er den Job aus. */ public class CronDaemon extends Thread { private Crontab crontab = null; public CronDaemon(Crontab crontab) { this.crontab = crontab; } public void run() { while(true) { System.out.println("Lese Crontab um " + (new java.util.Date())); Enumeration jobs = crontab.listEntries(); while (jobs.hasMoreElements()) { CrontabEntry entry = (CrontabEntry)jobs.nextElement(); System.out.println(entry + "\t" + entry.needsExecution()); if (entry.needsExecution()) entry.execute(); } // So, jetzt bis zur nächsten vollen Stunde schlafen gehen // Da unbekannt ist, wie lange die Ausführung der Jobs // gedauert hat, muss die Zeitspanne bis zur nächsten vollen // Stunde ausgerechnet werden. // Wenn uns jemand unterbricht, dann geht es sofort weiter. try { long now = (new Date()).getTime(); long hour = 1000*60*60; // 1 Stunde in Millisekunden long left = hour - (now%hour); this.sleep(left+450); } catch (Exception e) {} } } } --- Neue Klasse --- package javacodebook.thread.crontab; import java.util.*; /** * Eine minimalistische Cron-Tabelle */ public class Crontab { private static Crontab crontab = null; private static int id = 0; private Vector entries; private CronDaemon daemon; private Crontab() { entries = new Vector(); daemon = new CronDaemon(this); daemon.start(); } /** * Die Crontab ist ein sog. Singleton. Das heisst, es kann in einer * Anwendung max ein Objekt der Klasse geben. Mit getInstance() wird dieses * Objekt gelesen. */ public static Crontab getInstance() { if (crontab == null) crontab = new Crontab(); return crontab; } /** * Setzt einen neuen Eintrag in die Crontab. * @param hour Die Stunde (0-23) zu der der Eintrag ausgeführt werden soll. * Ein negativer Wert bedeutet, dass der Eintrag zu jeder vollen Stunde * ausgeführt wird. * @param weekday Der Wochentag, an dem der Eintrag ausgeführt werden soll. * Als Wert kann eine Konstante aus der Klasse Calendar genommen werden * (z.B. Calendar.SUNDAY). Ein negativer Wert bedeutet, dass der Eintrag * jeden Tag ausgeführt wird. * @param command das auszuführende Kommando * @param parameter Eine Reihe von Parametern, die dem Kommando bei der * Ausführung übergeben werden * @returns Die von der Crontab vergebene ID für den Eintrag */ public synchronized int addEntry(int hour, int weekday, Command command, Hashtable parameter) { int tmpId = id++; CrontabEntry entry = new CrontabEntry(tmpId, hour, weekday, command, parameter); entries.addElement(entry); return tmpId; } /** * Setzt einen neuen Eintrag in die Crontab. * @param hour Die Stunde (0-23) zu der der Eintrag ausgeführt werden soll. * Ein negativer Wert bedeutet, dass der Eintrag zu jeder vollean Stunde * ausgeführt wird. * @param weekday Der Wochentag, an dem der Eintrag ausgeführt werden soll. * Als Wert kann eine Konstante aus der Klasse Calendar genommen werden * (z.B. Calendar.SUNDAY). Ein negativer Wert bedeutet, dass der Eintrag * jeden Tag ausgeführt wird. * @param command das auszuführende Kommando * @returns Die von der Crontab vergebene ID für den Eintrag */ public synchronized int addEntry(int hour, int weekday, Command command) { int tmpId = id++; CrontabEntry entry = new CrontabEntry(tmpId, hour, weekday, command, null); entries.addElement(entry); return tmpId; } /** * Einen Eintrag aus der Crontab loeschen. * @param die ID des zu löschenden Eintrages */ public synchronized void removeEntry(int id) { for (int index=entries.size()-1; index>=0; index--) { CrontabEntry entry = (CrontabEntry)entries.elementAt(index); if (entry.id == id) { entries.removeElementAt(index); break; } } } /** * Einen Eintrag in der Crontab lesen. * @param die ID des zu löschenden Eintrages */ public synchronized CrontabEntry getEntry(int id) { CrontabEntry entry = null; for (int index=entries.size()-1; index>=0; index--) { entry = (CrontabEntry)entries.elementAt(index); if (entry.id == id) break; } return entry; } /** * Alle Einträge in der Crontab auflisten */ public synchronized Enumeration listEntries() { return entries.elements(); } } --- Neue Klasse --- package javacodebook.thread.crontab; import java.util.*; /** * Ein Eintrag in der Crontab. */ class CrontabEntry { protected int id = 0; protected int hour = 0; protected int weekday = 0; protected Command command = null; protected Hashtable parameter = null; /** * Erzeugt einen neuen Eintrag für die Crontab. Man kann nicht selber einen * neuen Eintrag erzeugen, sondern muß dies der Crontab überlassen. */ protected CrontabEntry(int id, int hour, int weekday, Command command, Hashtable parameter) { this.id = id; this.hour = hour; this.weekday = weekday; this.command = command; this.parameter = parameter; } public String toString() { StringBuffer buf = new StringBuffer(); buf.append(id); buf.append("\t"); buf.append(hour); buf.append("\t"); buf.append(weekday); buf.append("\t"); buf.append(command); buf.append("\t"); buf.append(parameter); return buf.toString(); } public boolean equals(Object otherEntry) { if ((otherEntry == null) || (!(otherEntry instanceof CrontabEntry))) return false; CrontabEntry tab = (CrontabEntry)otherEntry; return (this.id == tab.id); } public int getHour() { return hour; } public int getWeekday() { return weekday; } public Command getCommand() { return command; } public Hashtable getParameter() { return parameter; } public int getId() { return id; } /** * Es wird getestet, ob der Eintrag jetzt ausgeführt werden müßte. * Dazu wird die aktuelle Zeit mit der Zeit verglichen, zu der der Eintrag * ausgeführt werden soll. * @returns true wenn der Eintrag jetzt ausgeführt werden müßte. */ public boolean needsExecution() { boolean execute = false; // Zunächst einmal wird die aktuelle Stunde und der aktuelle Wochentag // herausgefunden. GregorianCalendar gc = new GregorianCalendar(); int now_hour = gc.get(Calendar.HOUR_OF_DAY); int now_weekday = gc.get(Calendar.DAY_OF_WEEK); // Wenn einer der vorgegebenen Werte negativ ist, dann handelt es sich // bei dem Wert um ein Asteriks. In diesem Falle werden die Werte // now_hour bzw. now_weekday auf aktuelle Werte gesetzt. if (hour < 0) now_hour = hour; if (weekday < 0) now_weekday = weekday; // Prüfen, ob der Eintrag jetzt ausgeführt werden muss. return (now_hour == hour && now_weekday == weekday); } /** * Das zu dem Eintrag gehörende Kommando wird ausgeführt. */ protected void execute() { try { if (parameter == null) command.execute(); else command.execute(parameter); } catch (Exception e) { } } } --- Neue Klasse --- package javacodebook.thread.crontab; import java.util.Calendar; /** * Startet die Crontab */ public class Starter { public static void main(String []args) { // Die Crontab erzeugen Crontab crontab = Crontab.getInstance(); // Testkommandos erzeugen TestCommand test1 = new TestCommand("Test1"); TestCommand test2 = new TestCommand("Test2"); // Kommandos mit den Zeiten für Ihre Ausführungs in // die Crontab schreiben crontab.addEntry(12, Calendar.MONDAY, test1); crontab.addEntry(-1, Calendar.WEDNESDAY, test2); } } --- Neue Klasse --- package javacodebook.thread.crontab; import java.util.Hashtable; /** * Ein einfaches Test-Command, um die Funktionsweise zu der Crontab zu testen. */ public class TestCommand implements Command { private String name; public TestCommand(String name) { this.name = name; } public void execute() { System.out.println( "Führe Test-Command '" + name + "'ohne Parameter aus." ); } public void execute(Hashtable parameter) { System.out.print( "Führe Test-Command '" + name + "' mit den folgenden Parametern aus: " ); System.out.println(parameter); } public String toString() { return "Test-Command '" + name + "'"; } }