package net.hyperic.sigar.win32;

import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.apache.log4j.Logger;

/**
 * A simple thread that runs forever monitoring the event log.
 */
public class EventLogThread implements Runnable {

    public static final int DEFAULT_INTERVAL = 60 * 1000;

    private static Logger logger =
        Logger.getLogger(EventLogThread.class.getName());

    private Thread thread = null;
    private static EventLogThread instance = null;
    private boolean shouldDie = false;
    private Set notifiers     = Collections.synchronizedSet(new HashSet());

    private String logName = "Application";
    private long interval  = 10 * 1000; // Default to 10 seconds

    public static synchronized EventLogThread getInstance() {
        if (instance == null) {
            instance = new EventLogThread();
        }

        return instance;
    }

    public void setInterval(long interval) {
        this.interval = interval;
    }

    public void setLogName(String logName) {
        this.logName = logName;
    }
    
    public synchronized void doStart() {
        if (this.thread != null) {
            return;
        }

        this.thread = new Thread(this, "EventLogThread");
        this.thread.setDaemon(true);
        this.thread.start();

        logger.debug(this.thread.getName() + " started");
    }

    public synchronized void doStop() {
        if (this.thread == null) {
            return;
        }
        die();
        this.thread.interrupt();
        logger.debug(this.thread.getName() + " stopped");
        this.thread = null;
    }

    public void add(EventLogNotification notifier) {
        this.notifiers.add(notifier);
    }

    public void remove(EventLogNotification notifier) {
        this.notifiers.remove(notifier);
    }

    private void handleEvents(EventLog log, int curEvent, int lastEvent)
    {
        for (int i = curEvent + 1; i <= lastEvent; i++) {

            EventLogRecord record;

            try {
                record = log.read(i);
            } catch (Win32Exception e) {
                logger.error("Unable to read event id " + i + ": " + e);
                continue;
            }

            synchronized (this.notifiers) {
                for (Iterator it = this.notifiers.iterator(); it.hasNext();)
                {
                    EventLogNotification notification =
                        (EventLogNotification)it.next();
                    if (notification.matches(record))
                        notification.handleNotification(record);
                }
            }
        }
    }

    public void run() {
        
        EventLog log = new EventLog();
        int curEvent;

        try {
            // Open the event log
            log.open(this.logName);

            curEvent = log.getNewestRecord();

            while (!shouldDie) {
                // XXX: Using the waitForChange() method would be a
                //      cleaner way to go, but we cannot interrupt
                //      a native system call.
                int lastEvent = log.getNewestRecord();
                if (lastEvent > curEvent) {
                    handleEvents(log, curEvent, lastEvent);
                }

                curEvent = lastEvent;

                try {
                    Thread.sleep(this.interval);
                } catch (InterruptedException e) {
                }
            }
            
            log.close();

        } catch (Win32Exception e) {
            logger.error("Unable to monitor event log:", e);
        } finally {
            try { log.close(); } 
            catch (Win32Exception e) {}}
    }

    public void die() {
        this.shouldDie = true;
    }
}

@@ -27,16 +27,44 @@
 win32;%0A%0A
+import java.io.IOException;%0A
 import j
@@ -111,16 +111,42 @@
 ashSet;%0A
+import java.util.HashMap;%0A
 import j
@@ -3823,11 +3823,1343 @@
 e;%0A    %7D
+%0A%0A    public static void main(String%5B%5D args) %7B%0A        HashMap logs = new HashMap();%0A        if (args.length == 0) %7B%0A            args = new String%5B%5D %7B%0A                %22System%22, %22Application%22, %22Security%22%0A            %7D;%0A        %7D%0A%0A        EventLogNotification watcher =%0A            new EventLogNotification() %7B%0A                public boolean matches(EventLogRecord record) %7B%0A                    return true;%0A                %7D%0A%0A                public void handleNotification(EventLogRecord record) %7B %0A                    System.out.println(record);%0A                %7D%0A            %7D;%0A%0A        for (int i=0; i%3Cargs.length; i++) %7B%0A            String name = args%5Bi%5D;%0A            EventLogThread eventLogThread = %0A                new EventLogThread();%0A%0A            eventLogThread.setLogName(name);%0A            eventLogThread.doStart();%0A            eventLogThread.setInterval(1000);%0A            eventLogThread.add(watcher);%0A            logs.put(name, eventLogThread);%0A        %7D%0A%0A        System.out.println(%22Press any key to stop%22);%0A        try %7B%0A            System.in.read();%0A        %7D catch (IOException e) %7B %7D%0A%0A        for (Iterator it = logs.values().iterator();%0A             it.hasNext();)%0A        %7B%0A            EventLogThread eventLogThread =%0A                (EventLogThread)it.next();%0A            eventLogThread.doStop();%0A        %7D%0A    %7D
 %0A%7D%0A

add main method to watch event logs