1 # Copyright 2014 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
9 from devil
.utils
import cmd_helper
10 from pylib
import constants
13 _PROGUARD_CLASS_RE
= re
.compile(r
'\s*?- Program class:\s*([\S]+)$')
14 _PROGUARD_SUPERCLASS_RE
= re
.compile(r
'\s*? Superclass:\s*([\S]+)$')
15 _PROGUARD_SECTION_RE
= re
.compile(
16 r
'^(?:Interfaces|Constant Pool|Fields|Methods|Class file attributes) '
18 _PROGUARD_METHOD_RE
= re
.compile(r
'\s*?- Method:\s*(\S*)[(].*$')
19 _PROGUARD_ANNOTATION_RE
= re
.compile(r
'\s*?- Annotation \[L(\S*);\]:$')
20 _PROGUARD_ANNOTATION_CONST_RE
= (
21 re
.compile(r
'\s*?- Constant element value.*$'))
22 _PROGUARD_ANNOTATION_VALUE_RE
= re
.compile(r
'\s*?- \S+? \[(.*)\]$')
24 _PROGUARD_PATH_SDK
= os
.path
.join(
25 constants
.PROGUARD_ROOT
, 'lib', 'proguard.jar')
26 _PROGUARD_PATH_BUILT
= (
27 os
.path
.join(os
.environ
['ANDROID_BUILD_TOP'], 'external', 'proguard',
28 'lib', 'proguard.jar')
29 if 'ANDROID_BUILD_TOP' in os
.environ
else None)
31 _PROGUARD_PATH_SDK
if os
.path
.exists(_PROGUARD_PATH_SDK
)
32 else _PROGUARD_PATH_BUILT
)
36 """Dumps class and method information from a JAR into a dict via proguard.
39 jar_path: An absolute path to the JAR file to dump.
41 A dict in the following format:
61 with tempfile
.NamedTemporaryFile() as proguard_output
:
62 cmd_helper
.RunCmd(['java', '-jar',
69 '-dump', proguard_output
.name
])
70 return Parse(proguard_output
)
72 def Parse(proguard_output
):
78 annotation_has_value
= False
82 for line
in proguard_output
:
83 line
= line
.strip('\r\n')
85 m
= _PROGUARD_CLASS_RE
.match(line
)
88 'class': m
.group(1).replace('/', '.'),
93 results
['classes'].append(class_result
)
95 annotation_has_value
= False
102 m
= _PROGUARD_SUPERCLASS_RE
.match(line
)
104 class_result
['superclass'] = m
.group(1).replace('/', '.')
107 m
= _PROGUARD_SECTION_RE
.match(line
)
110 annotation_has_value
= False
114 m
= _PROGUARD_METHOD_RE
.match(line
)
117 'method': m
.group(1),
120 class_result
['methods'].append(method_result
)
122 annotation_has_value
= False
125 m
= _PROGUARD_ANNOTATION_RE
.match(line
)
127 # Ignore the annotation package.
128 annotation
= m
.group(1).split('/')[-1]
130 method_result
['annotations'][annotation
] = None
132 class_result
['annotations'][annotation
] = None
136 if not annotation_has_value
:
137 m
= _PROGUARD_ANNOTATION_CONST_RE
.match(line
)
138 annotation_has_value
= bool(m
)
140 m
= _PROGUARD_ANNOTATION_VALUE_RE
.match(line
)
143 method_result
['annotations'][annotation
] = m
.group(1)
145 class_result
['annotations'][annotation
] = m
.group(1)
146 annotation_has_value
= None