import java.io.*;

/** A simple automatic recompilation system for Java.
 ** This simply scans the <tt>.java</tt> files in the supplied directory,
 ** waiting for any of them to change, at which point it recompiles
 ** them.
 ** When there are no changed files, it sleeps for a few seconds.
 ** (The dormancy time is currently fixed at 5secs.)
 ** <p>
 ** This version has the following limitations:
 ** <OL>
 ** <LI> One directory only.
 ** <LI> Files not compiled before AutoCompile starts do not get compiled
 **      until their next change.
 ** <LI> Files added to the directory after AutoCompile starts are not spotted.
 ** </OL>
 **
 ** @author Dave Lloyd
 ** @version 1.0
 **/


public class AutoCompile
{
    static int SleepTime = 5000 /* ms */;

    SourceFile[ ] files;

    AutoCompile (String Directory)
    {
        this.SleepTime = SleepTime;

        File Dir = new File (Directory);

        String[ ] files = Dir.list (new ExtnFilter (".java"));

        this.files = new SourceFile [files.length];

        for (int n = 0; n < files.length; n++)
            this.files [n] = new SourceFile (Directory + "/" + files [n]);
    }

    boolean update ()
    {
        boolean changed = false;

        for (int n = 0; n < files.length; n++)
            if (files [n].Changed())
                { files [n].Compile(); changed = true; }

        return changed;
    }

    /** For stand-alone use, AutoCompile has a main.
     ** It takes one string argument: the directory to watch.
     ** Usage: java AutoCompile <dir>
     ** If <dir> is omitted, the current directory is assumed.
     **/

    public static void main (String[ ] args)
    {
        AutoCompile AC = new AutoCompile (args.length == 0 ? "." : args [0]);

        do 
        { 
            if (! AC.update ()) 
                try { System.out.println ("Sleeping..."); Thread.sleep (SleepTime); } 
                catch (InterruptedException X) { System.out.println ("... woken up"); }
        }
        while (true);
    }
}

/** SourceFile extends File to understand compilation and records the last compilation time. 
 **/

class SourceFile extends File
{
    public long lastCompiled;

    SourceFile (String name) { super (name); lastCompiled = this.lastModified(); }

    boolean Changed () { return lastModified () > lastCompiled; }

    void Compile ()
    {
        Runtime runtime = Runtime.getRuntime();

        lastCompiled = lastModified();

        try { 
            System.out.println ("Compiling "+this+" ...");
            runtime.exec ("javac "+this).waitFor(); 
        } catch (Exception X) { System.out.println ("... something went wrong just then?"); }
    }
}

/** ExtnFilter is an implementation of FilenameFilter that accepts only files with the supplied extension.
 **/

class ExtnFilter implements FilenameFilter
{
    String extn;

    ExtnFilter (String extn) { this.extn = extn; }

    public boolean accept (File Dir, String name)
        { return name.substring (name.lastIndexOf (".")).equals (extn); }
}

