//
// Copyright (c) 2006, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
//   4 Nov 06  Brian Frank  Creation
//

using compiler

**
** Run the Java compiler to produce a directory of Java classfiles.
**
class CompileJava : JdkTask
{

//////////////////////////////////////////////////////////////////////////
// Construction
//////////////////////////////////////////////////////////////////////////

  **
  ** Construct uninitialized javac task
  **
  new make(BuildScript script)
    : super(script)
  {
    this.params = (script.config("javacParams") ?: "").split.findAll |s| { !s.isEmpty }
  }

//////////////////////////////////////////////////////////////////////////
// Configuration
//////////////////////////////////////////////////////////////////////////

  **
  ** Extra parameters to pass to javac.  Default is
  ** to target 1.5 classfiles.
  **
  Str[] params

//////////////////////////////////////////////////////////////////////////
// Add
//////////////////////////////////////////////////////////////////////////

  **
  ** Add all the jars found in lib/java/ext and lib/java/ext/os
  ** to the class path.
  **
  Void cpAddExtJars()
  {
    cpAddJars(script.devHomeDir + `lib/java/ext/`)
    cpAddJars(script.devHomeDir + `lib/java/ext/$Env.cur.platform/`)
  }

  **
  ** Add all the jar files found in the specified
  ** directory to the classpath.
  **
  Void cpAddJars(File dir)
  {
    dir.list.each |File f| { if (f.ext == "jar") cp.add(f) }
  }

//////////////////////////////////////////////////////////////////////////
// Run
//////////////////////////////////////////////////////////////////////////

  **
  ** Run the javac task
  **
  override Void run()
  {
    log.info("CompileJava")

    try
    {
      // build command
      cmd := [javacExe]

      // always assume UTF-8
      cmd.add("-encoding").add("utf-8")

      cmd.addAll(params)

      // -d outDir
      if (outDir != null)
      {
        cmd.add("-d").add(outDir.osPath)
      }

      // Only add files from java.home if the JDK being used to compile is for
      // Java 8 or earlier.
      if (Env.cur.javaVersion <= 8)
      {
        // -bootclasspath rt.jar for current environment; this might
        // different from jdkHomeDir if cross-compiling; this logic is a
        // simpler version of what compilerJava::ClassPath does in Java FFI
        javaLib := File.os(Env.cur.vars.get("java.home", "") + File.sep + "lib")
        bootJars := [javaLib+`rt.jar`, javaLib+`jce.jar`]
        cmd.add("-bootclasspath")
        cmd.add(bootJars.join(File.pathSep) |File f->Str| { return f.osPath })
      }

      // -cp <classpath>
      cmd.add("-cp")
      cmd.add(cp.join(File.pathSep) |File f->Str| { return f.osPath })

      // src files/dirs
      cwd := script.scriptDir
      listFiles(cmd, cwd, src)
      log.debug(cmd.join(" "))
      r := Process(cmd, cwd).run.join
      if (r != 0) throw Err.make
    }
    catch (Err e)
    {
      throw fatal("CompileJava failed", e)
    }
  }

  internal Void listFiles(Str[] list, File cwd, File[] files)
  {
    files.each |File f|
    {
      // if directory, then recurse
      if (f.isDir) listFiles(list, cwd, f.list)

      // use dir/*.java on Windows so that command line doesn't
      // get too long but list every file on other operating systems
      if (Env.cur.os == "win32")
      {
        if (f.isDir && f.list.any |x| { x.ext == "java" })
          list.add(f.plus(`*.java`).osPath)
      }
      else if (f.ext == "java")
      {
        list.add(f.osPath)
      }
    }
  }

//////////////////////////////////////////////////////////////////////////
// Fields
//////////////////////////////////////////////////////////////////////////

  ** Class path - list of jars to compile against,
  ** rt.jar is automatically included
  File[] cp := File[,]

  ** List of source files or directories to compile.  If
  ** a directory is specified, then it is recursively searched
  ** for all ".java" files.
  File[] src := File[,]

  ** Output directory
  File? outDir


}