# Copyright (C) 2017 The Android Open Source Project
#
# 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.

# War packaging.

jar_filetype = FileType([".jar"])

def _add_context(in_file, output):
  input_path = in_file.path
  return [
    'unzip -qd %s %s' % (output, input_path)
  ]

def _add_file(name, in_file, output):
  output_path = output
  input_path = in_file.path
  short_path = in_file.short_path
  n = in_file.basename

  if n != 'web.xml' and short_path.startswith('%s-' % name):
    n = short_path.split('/')[0] + '-' + n

  output_path += n

  return [
    'test -L %s || ln -s $(pwd)/%s %s' % (output_path, input_path, output_path)
  ]

def _make_war(input_dir, output):
  return '(%s)' % ' && '.join([
    'root=$(pwd)',
    'cd %s' % input_dir,
    "find . -exec touch -t 198001010000 '{}' ';' 2> /dev/null",
    'zip -9qr ${root}/%s .' % (output.path),
  ])

def _war_impl(ctx):
  war = ctx.outputs.war
  build_output = war.path + '.build_output'
  inputs = []

  cmd = [
    'set -e;rm -rf ' + build_output,
    'mkdir -p ' + build_output,
    'mkdir -p %s/WEB-INF/lib' % build_output,
  ]

  transitive_lib_deps = set()
  for l in ctx.attr.libs:
    if hasattr(l, 'java'):
      transitive_lib_deps += l.java.transitive_runtime_deps
    elif hasattr(l, 'files'):
      transitive_lib_deps += l.files

  for dep in transitive_lib_deps:
    cmd += _add_file(ctx.attr.name, dep, build_output + '/WEB-INF/lib/')
    inputs.append(dep)

  if ctx.attr.web_xml:
    for web_xml in ctx.attr.web_xml.files:
      inputs.append(web_xml)
      cmd += _add_file(ctx.attr.name, web_xml, build_output + '/WEB-INF/')

  transitive_context_deps = set()
  if ctx.attr.context:
    for jar in ctx.attr.context:
      if hasattr(jar, 'java'):
        transitive_context_deps += jar.java.transitive_runtime_deps
      elif hasattr(jar, 'files'):
        transitive_context_deps += jar.files
  for dep in transitive_context_deps:
    cmd += _add_context(dep, build_output)
    inputs.append(dep)

  # Add zip war
  cmd.append(_make_war(build_output, war))

  ctx.action(
    inputs = inputs,
    outputs = [war],
    mnemonic = 'WAR',
    command = '\n'.join(cmd),
    use_default_shell_env = True,
  )

# context: go to the root directory
# libs: go to the WEB-INF/lib directory
# web_xml: go to the WEB-INF directory
_pkg_war = rule(
    attrs = {
        "context": attr.label_list(allow_files = True),
        "libs": attr.label_list(allow_files = jar_filetype),
        "web_xml": attr.label(allow_files = True),
    },
    outputs = {"war": "%{name}.war"},
    implementation = _war_impl,
)

def pkg_war(name, context = [], **kwargs):
  _pkg_war(
    name = name,
    context = context,
    **kwargs
  )
