1#!/usr/bin/env python
2#
3# Copyright (C) 2013 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the 'License');
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9#      http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an 'AS IS' BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18"""Check that a jar file contains only allowed packages.
19
20Given a jar file (typically, the result of running jarjar to rename packages)
21and a whitelist file of allowed package names, one per line, check that all the
22classes in the jar are in one of those packages.
23"""
24
25import contextlib
26import sys
27import zipfile
28
29
30def JarCheck(jar_path, whitelist_path):
31  """Checks that the files in the jar are in whitelisted packages.
32
33  Args:
34    jar_path: The path to the .jar file to be checked.
35    whitelist_path: The path to the whitelist file.
36  Returns:
37    A list of files that are not in whitelisted packages.
38  """
39  with open(whitelist_path) as whitelist_file:
40    allowed_packages = tuple(x.replace('.', '/').replace('\n', '/')
41                             for x in whitelist_file)
42
43  with contextlib.closing(zipfile.ZipFile(jar_path)) as jar:
44    jar_contents = jar.namelist()
45
46  invalid_files = []
47  for filename in jar_contents:
48    # Zipfile entries with a trailing / are directories, we can ignore these.
49    # Also ignore jar meta-info.
50    if filename.endswith('/') or filename.startswith('META-INF/'):
51      continue
52    if not filename.startswith(allowed_packages):
53      invalid_files.append(filename)
54
55  return invalid_files
56
57
58def main(argv):
59  if len(argv) != 3:
60    print >>sys.stderr, 'Usage: %s jar_file whitelist_file' % argv[0]
61    return 2
62  invalid_files = JarCheck(argv[1], argv[2])
63  invalid_file_count = len(invalid_files)
64  if invalid_file_count == 0:
65    return 0
66  print >>sys.stderr, ('jar_check found %s files not in a whitelisted package:'
67                       % invalid_file_count)
68  for f in invalid_files:
69    print >>sys.stderr, f
70  return 1
71
72
73if __name__ == '__main__':
74  sys.exit(main(sys.argv))
75