#!/usr/bin/env python3
# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""update_api.py - Update committed Cronet API."""



import argparse
import filecmp
import fileinput
import hashlib
import os
import re
import shutil
import sys
import tempfile


REPOSITORY_ROOT = os.path.abspath(
    os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir))

sys.path.insert(0, os.path.join(REPOSITORY_ROOT, 'build/android/gyp'))
from util import build_utils  # pylint: disable=wrong-import-position

# Filename of dump of current API.
API_FILENAME = os.path.abspath(os.path.join(
    os.path.dirname(__file__), '..', 'android', 'api.txt'))
# Filename of file containing the interface API version number.
INTERFACE_API_VERSION_FILENAME = os.path.abspath(os.path.join(
    os.path.dirname(__file__), '..', 'android', 'interface_api_version.txt'))

# Regular expression that catches the beginning of lines that declare classes.
# The first group returned by a match is the class name.
CLASS_RE = re.compile(r'.*(class|interface) ([^ ]*) .*\{')

# Regular expression that matches a string containing an unnamed class name,
# for example 'Foo$1'.
UNNAMED_CLASS_RE = re.compile(r'.*\$[0-9]')

# javap still prints internal (package private, nested...) classes even though
# -protected is passed so they need to be filtered out.
INTERNAL_CLASS_RE = re.compile(
    r'^(?!public ((final|abstract) )?(class|interface)).*')

JAR_PATH = os.path.join(build_utils.JAVA_HOME, 'bin', 'jar')
JAVAP_PATH = os.path.join(build_utils.JAVA_HOME, 'bin', 'javap')


def generate_api(api_jar, output_filename):
  # Dumps the API in |api_jar| into |outpuf_filename|.

  with open(output_filename, 'w') as output_file:
    output_file.write(
        'DO NOT EDIT THIS FILE, USE update_api.py TO UPDATE IT\n\n')

  # Extract API class files from api_jar.
  temp_dir = tempfile.mkdtemp()
  old_cwd = os.getcwd()
  api_jar_path = os.path.abspath(api_jar)
  jar_cmd = '%s xf %s' % (os.path.relpath(JAR_PATH, temp_dir), api_jar_path)
  os.chdir(temp_dir)
  if os.system(jar_cmd):
    print('ERROR: jar failed on ' + api_jar)
    return False
  os.chdir(old_cwd)
  shutil.rmtree(os.path.join(temp_dir, 'META-INF'), ignore_errors=True)

  # Collect names of all API class files
  api_class_files = []
  for root, _, filenames in os.walk(temp_dir):
    api_class_files += [os.path.join(root, f) for f in filenames]
  api_class_files.sort()

  # Dump API class files into |output_filename|
  javap_cmd = (
      '%s -protected %s >> %s' % (
          JAVAP_PATH, ' '.join(api_class_files), output_filename)
  ).replace('$', '\\$')
  if os.system(javap_cmd):
    print('ERROR: javap command failed: ' + javap_cmd)
    return False
  shutil.rmtree(temp_dir)

  # Strip out pieces we don't need to compare.
  output_file = fileinput.FileInput(output_filename, inplace=True)
  skip_to_next_class = False
  md5_hash = hashlib.md5()
  for line in output_file:
    # Skip 'Compiled from ' lines as they're not part of the API.
    if line.startswith('Compiled from "'):
      continue
    if CLASS_RE.match(line):
      skip_to_next_class = (
          # Skip internal classes, they aren't exposed.
          UNNAMED_CLASS_RE.match(line)) or (INTERNAL_CLASS_RE.match(line))
    if skip_to_next_class:
      skip_to_next_class = line != '}'
      continue
    md5_hash.update(line.encode('utf8'))
    sys.stdout.write(line)
  output_file.close()
  with open(output_filename, 'a') as output_file:
    output_file.write('Stamp: %s\n' % md5_hash.hexdigest())
  return True


def check_up_to_date(api_jar):
  # Returns True if API_FILENAME matches the API exposed by |api_jar|.

  [_, temp_filename] = tempfile.mkstemp()
  if not generate_api(api_jar, temp_filename):
    return False
  ret = filecmp.cmp(API_FILENAME, temp_filename)
  os.remove(temp_filename)
  return ret


def check_api_update(old_api, new_api):
  # Enforce that lines are only added when updating API.
  new_hash = hashlib.md5()
  old_hash = hashlib.md5()
  seen_stamp = False
  with open(old_api, 'r') as old_api_file, open(new_api, 'r') as new_api_file:
    for old_line in old_api_file:
      while True:
        new_line = new_api_file.readline()
        if seen_stamp:
          print('ERROR: Stamp is not the last line.')
          return False
        if new_line.startswith('Stamp: ') and old_line.startswith('Stamp: '):
          if old_line != 'Stamp: %s\n' % old_hash.hexdigest():
            print('ERROR: Prior api.txt not stamped by update_api.py')
            return False
          if new_line != 'Stamp: %s\n' % new_hash.hexdigest():
            print('ERROR: New api.txt not stamped by update_api.py')
            return False
          seen_stamp = True
          break
        new_hash.update(new_line.encode('utf8'))
        if new_line == old_line:
          break
        if not new_line:
          if old_line.startswith('Stamp: '):
            print('ERROR: New api.txt not stamped by update_api.py')
          else:
            print('ERROR: This API was modified or removed:')
            print('           ' + old_line)
            print('       Cronet API methods and classes cannot be modified.')
          return False
      old_hash.update(old_line.encode('utf8'))
  if not seen_stamp:
    print('ERROR: api.txt not stamped by update_api.py.')
    return False
  return True


def main(args):
  parser = argparse.ArgumentParser(description='Update Cronet api.txt.')
  parser.add_argument('--api_jar',
                      help='Path to API jar (i.e. cronet_api.jar)',
                      required=True,
                      metavar='path/to/cronet_api.jar')
  parser.add_argument('--ignore_check_errors',
                      help='If true, ignore errors from verification checks',
                      required=False,
                      default=False,
                      action='store_true')
  opts = parser.parse_args(args)

  if check_up_to_date(opts.api_jar):
    return True

  [_, temp_filename] = tempfile.mkstemp()
  if not generate_api(opts.api_jar, temp_filename):
    os.remove(temp_filename)
    return False

  update_ok = check_api_update(API_FILENAME, temp_filename)
  if not update_ok:
    if opts.ignore_check_errors:
      print('ignore_check_errors set, updating API anyway')
    else:
      os.remove(temp_filename)
      return False

  # Update API version number to new version number
  with open(INTERFACE_API_VERSION_FILENAME, 'r+') as f:
    version = int(f.read())
    f.seek(0)
    f.write(str(version + 1))
  # Update API file to new API
  shutil.move(temp_filename, API_FILENAME)
  return True


if __name__ == '__main__':
  sys.exit(0 if main(sys.argv[1:]) else -1)
