# Copyright 2014 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

java_filetype = FileType([".java"])
jar_filetype = FileType([".jar"])
srcjar_filetype = FileType([".jar", ".srcjar"])

JAVA_PATH='tools/jdk/jdk/bin/'

def is_windows(config):
  return config.fragment(cpp).compiler.startswith("windows_")

def path_separator(ctx):
  if is_windows(ctx.configuration):
    return ";"
  else:
    return ":"

# This is a quick and dirty rule to make Bazel compile itself. It's not
# production ready.

def java_library_impl(ctx):
  class_jar = ctx.outputs.class_jar
  compile_time_jars = set(order="link")
  runtime_jars = set(order="link")
  for dep in ctx.attr.deps:
    compile_time_jars += dep.compile_time_jars
    runtime_jars += dep.runtime_jars

  jars = jar_filetype.filter(ctx.files.jars)
  compile_time_jars += jars
  runtime_jars += jars
  compile_time_jars_list = list(compile_time_jars) # TODO: This is weird.

  build_output = class_jar.path + ".build_output"
  sources = ctx.files.srcs

  sources_param_file = ctx.new_file(
      ctx.configuration.bin_dir, class_jar, "-2.params")
  ctx.file_action(
      output = sources_param_file,
      content = cmd_helper.join_paths("\n", set(sources)),
      executable = False)

  # Cleaning build output directory
  cmd = "set -e;rm -rf " + build_output + ";mkdir " + build_output + "\n"
  if ctx.files.srcs:
    cmd += JAVA_PATH + "javac"
    if compile_time_jars:
      cmd += " -classpath '" + cmd_helper.join_paths(path_separator(ctx), compile_time_jars) + "'"
    cmd += " -d " + build_output + " @" + sources_param_file.path + "\n"

  # We haven't got a good story for where these should end up, so
  # stick them in the root of the jar.
  for r in ctx.files.resources:
    cmd += "cp %s %s\n" % (r.path, build_output)
  cmd += (JAVA_PATH + "jar cf " + class_jar.path + " -C " + build_output + " .\n" +
         "touch " + build_output + "\n")
  ctx.action(
    inputs = (sources + compile_time_jars_list + [sources_param_file] +
              ctx.files.resources),
    outputs = [class_jar],
    mnemonic='Javac',
    command=cmd,
    use_default_shell_env=True)

  runfiles = ctx.runfiles(collect_data = True)

  return struct(files = set([class_jar]),
                compile_time_jars = compile_time_jars + [class_jar],
                runtime_jars = runtime_jars + [class_jar],
                runfiles = runfiles)


def java_binary_impl(ctx):
  library_result = java_library_impl(ctx)

  deploy_jar = ctx.outputs.deploy_jar
  manifest = ctx.outputs.manifest
  build_output = deploy_jar.path + ".build_output"
  main_class = ctx.attr.main_class
  ctx.file_action(
    output = manifest,
    content = "Main-Class: " + main_class + "\n",
    executable = False)

  # Cleaning build output directory
  cmd = "set -e;rm -rf " + build_output + ";mkdir " + build_output + "\n"
  for jar in library_result.runtime_jars:
    cmd += "unzip -qn " + jar.path + " -d " + build_output + "\n"
  cmd += (JAVA_PATH + "jar cmf " + manifest.path + " " +
         deploy_jar.path + " -C " + build_output + " .\n" +
         "touch " + build_output + "\n")

  ctx.action(
    inputs=list(library_result.runtime_jars) + [manifest],
    outputs=[deploy_jar],
    mnemonic='Deployjar',
    command=cmd,
    use_default_shell_env=True)

  # Write the wrapper.
  executable = ctx.outputs.executable
  ctx.file_action(
    output = executable,
    content = '\n'.join([
        "#!/bin/bash",
        "# autogenerated - do not edit.",
        "case \"$0\" in",
        "/*) self=\"$0\" ;;",
        "*)  self=\"$PWD/$0\";;",
        "esac",
        "",
        "if [[ -z \"$JAVA_RUNFILES\" ]]; then",
        "  if [[ -e \"${self}.runfiles\" ]]; then",
        "    export JAVA_RUNFILES=\"${self}.runfiles\"",
        "  fi",
        "  if [[ -n \"$JAVA_RUNFILES\" ]]; then",
        "    export TEST_SRCDIR=${TEST_SRCDIR:-$JAVA_RUNFILES}",
        "  fi",
        "fi",
        "",

        "jvm_bin=%s" % (ctx.file.javabin.path),
        "if [[ ! -x ${jvm_bin} ]]; then",
        "  jvm_bin=$(which java)",
        "fi",

        # We extract the .so into a temp dir. If only we could mmap
        # directly from the zip file.
        "DEPLOY=$(dirname $self)/$(basename %s)" % deploy_jar.path,

        # This works both on Darwin and Linux, with the darwin path
        # looking like tmp.XXXXXXXX.{random}
        "SO_DIR=$(mktemp -d -t tmp.XXXXXXXXX)",
        "function cleanup() {",
        "  rm -rf ${SO_DIR}",
        "}",
        "trap cleanup EXIT",
        "unzip -q -d ${SO_DIR} ${DEPLOY} \"*.so\" \"*.dll\" \"*.dylib\" >& /dev/null",
        ("${jvm_bin} -Djava.library.path=${SO_DIR} %s -jar $DEPLOY \"$@\""
         % ' '.join(ctx.attr.jvm_flags)) ,
        "",
        ]),
    executable = True)

  runfiles = ctx.runfiles(files = [
      deploy_jar, executable] + ctx.files.jvm, collect_data = True)
  files_to_build = set([deploy_jar, manifest, executable])
  files_to_build += library_result.files

  return struct(files = files_to_build, runfiles = runfiles)


def java_import_impl(ctx):
  # TODO(bazel-team): Why do we need to filter here? The attribute
  # already says only jars are allowed.
  jars = set(jar_filetype.filter(ctx.files.jars))
  runfiles = ctx.runfiles(collect_data = True)
  return struct(files = jars,
                compile_time_jars = jars,
                runtime_jars = jars,
                runfiles = runfiles)


java_library_attrs = {
    "data": attr.label_list(allow_files=True, cfg=DATA_CFG),
    "resources": attr.label_list(allow_files=True),
    "srcs": attr.label_list(allow_files=java_filetype),
    "jars": attr.label_list(allow_files=jar_filetype),
    "deps": attr.label_list(
        allow_files=False,
        providers = ["compile_time_jars", "runtime_jars"]),
    }

java_library = rule(
    java_library_impl,
    attrs = java_library_attrs,
    outputs = {
        "class_jar": "lib%{name}.jar",
    })

java_binary_attrs_common = java_library_attrs + {
    "jvm_flags": attr.string_list(),
    "jvm": attr.label(default=Label("//tools/jdk:jdk"), allow_files=True),
    "javabin": attr.label(default=Label("//tools/jdk:java"), single_file=True),
    "args": attr.string_list(),
}

java_binary_attrs = java_binary_attrs_common + {
    "main_class": attr.string(mandatory=True),
}

java_binary_outputs = {
    "class_jar": "lib%{name}.jar",
    "deploy_jar": "%{name}_deploy.jar",
    "manifest": "%{name}_MANIFEST.MF"
}

java_binary = rule(java_binary_impl,
   executable = True,
   attrs = java_binary_attrs,
   outputs = java_binary_outputs)

java_test = rule(java_binary_impl,
   executable = True,
   attrs = java_binary_attrs_common + {
       "main_class": attr.string(default="org.junit.runner.JUnitCore"),
       # TODO(bazel-team): it would be better if we could offer a
       # test_class attribute, but the "args" attribute is hard
       # coded in the bazel infrastructure.
   },
   outputs = java_binary_outputs,
   test = True,
)

java_import = rule(
    java_import_impl,
    attrs = {
        "jars": attr.label_list(allow_files=jar_filetype),
        "srcjar": attr.label(allow_files=srcjar_filetype),
    })
