// UpdateDir.java
//
// You may use and distribute this example. This program is 
// provided WITHOUT WARRANTY either expressed or implied.
//
// Copyright Henrik Björkman 1998
//
// Description: See usage below.
//
// History:
// 0.0 Created by Henrik Björkman 1998-06-09
// 0.1 Better error info. Added options. Henrik 2000-08-06
// 0.2 If time diff is one hour do not copy. Henrik 2001-12-01
// 0.3 More normal usage. 2001-12-23

import java.io.*;

/*
class ReadStreamThread extends Thread
{
  DataInputStream in;

  static void error(String str)
  {
    System.err.println("UpdateDir: " + str);
    System.exit(0);
  }

  public ReadStreamThread(InputStream in)
  {
    this.in=new DataInputStream(in);
    this.start();
  }
  
  public void run()
  {
    try
    {
      while (true) 
      {
        int ch=1;
        ch = in.read();
        if (ch<0) break;
        System.out.print((char)ch);
      }
    }
    catch(IOException e) 
    {
      error("IOException " + e);
    }
  }
}
*/

/**
 * Copy files in <dir1> that don't exist or are older in <dir2>
 */
public class UpdateDir
{
  static String copyCommand="cp";
  static String commandFileName="/tmp/files2copy";
  static String eoln="\n";
  static FileWriter out;
  static String dir=null;
  static boolean dont_run_script=false;

  static void error(String str)
  {
    System.err.println("UpdateDir: " + str);
    System.exit(0);
  }

  static void debug(String str)
  {
    //error(str);
  }

  static void println(String str)
  {
    System.out.println(str);
  }

  static void process_file(String src_name, String dst_name, int depth) throws IOException 
  {
    //File f1=new File(src_dir+name);
    //File f2=new File(dst_dir+name);        
    File f1=new File(src_name);
    File f2=new File(dst_name);        

    if (depth>50) {error("to deep!");}

    if (!f1.exists())
    {
      println("Source file not found: "+f1.getAbsolutePath());
      return;
    }

    if (f1.isDirectory())
    { 
      if (!f2.exists())
      {
        f2.mkdirs();
      }

      int i;
      String[] n;
      //println(name+File.separator);
      n=f1.list();
      for (i=0;i<n.length;i++)
      {
        process_file(src_name+File.separator+n[i], dst_name+File.separator+n[i], depth+1);
      }
    }
    else if (f1.isFile())
    {
      /* kolla om f2 inte finns eller är äldre */
      if ((!f2.exists()) || (!f2.isFile()) || (f2.lastModified()<f1.lastModified()))
      {
        if (Math.abs(f2.lastModified()-f1.lastModified())==(1000*60*60))
        {
          println("ignoring "+src_name+" (one hour diff)");
        }
        else
        {
          //String cmd=copyCommand+" \""+f1.getAbsolutePath()+"\" \""+f2.getAbsolutePath()+"\"";
          String cmd=copyCommand+" \""+src_name+"\" \""+dst_name+"\"";
          println("found "+src_name);
          out.write(cmd+eoln);
        }
      }
    }
    else
    {
      println(src_name+" ?");
    }

  }


  public static void help()
  {
      println("");
      println("Usage: java UpdateDir [option]... source... destdir");
      println("");
      println("Copy files but overwrite only older files. Ignore 1 hour diff.");
      println("");
      println("source: Name and path to one or more files and or directories");
      println("destdir: Name and path to destination directory");
      println("");
      println("options:");
      println("-l     Only make a script file (don't do the copying)");
      println("-o<n>  Set name of script file to <n>");
      //System.exit(0);
  }


  public static void main(String args[]) 
  {
    debug("begin");


    // Special in case of dos based os.
    if (System.getProperty("os.name").toUpperCase().indexOf("WINDOWS")>=0) 
    {
      debug("dos");
      copyCommand="copy";
      commandFileName="c:\\temp\\files2copy.bat";
      eoln="\r\n";
    }


    int i=0;

    while (i<args.length)
    {
      if (args[i].charAt(0)!='-') break;
      if (args[i].length()<2) {help();return;}
      switch(args[i].charAt(1))
      {
        case 'l' : dont_run_script=true;break;
        case 'o' : commandFileName=args[i].substring(2);break;
        default  : help();break;
      }
      i++;
    }

    if (args.length < 2 ) {help();return;}


    String dst_dir=args[args.length-1];

    // Check that destination exist and if directory is writable
    File f2=new File(dst_dir);
    if (!f2.exists()) {f2.mkdirs();}
    if (!f2.canWrite())
    {
      error("Destination is not writable or destination directory not found.");
    }

    File commandFile=new File(commandFileName);
    File dir=new File(commandFile.getParent());
    if (!dir.exists()) {dir.mkdirs();}


    try
    {
      out=new FileWriter(commandFile);

      println("writing "+commandFileName);

      while (i<args.length-1)
      {
        String src_name=args[i++];
        File f1=new File(src_name);
        if (!f1.exists())
        {
          println("Source file not found: "+f1.getAbsolutePath());
        }
        else
        {
          println("in "+f1.getName());
          process_file(src_name,dst_dir+File.separator+f1.getName(),0);
        }
      }


      out.close();

    }
    catch(IOException e) 
    {
      error("IOException " + e);
    }


    try
    {
      if (dont_run_script==false)
      {
        println("running "+commandFileName);

        Process pid=Runtime.getRuntime().exec(commandFileName);

        new ReadStreamThread(pid.getInputStream(),null);
        new ReadStreamThread(pid.getErrorStream(),System.out);

        pid.waitFor();
        pid.destroy();
      }
    }
    catch(InterruptedException e)
    {
      error(""+e);
    }
    catch(IOException e) 
    {
      error("IOException " + e);
    }

    //commandFile.delete();


    debug("total memory: "+Runtime.getRuntime().totalMemory());
    debug("free memory: "+Runtime.getRuntime().freeMemory());
    debug("end");
    System.exit(0);
  }
}


