Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 # TODO (qinmin): Need to refactor this file as base should not know about | |
| 7 # higher level concepts. Currently this file has knowledge about higher level | |
| 8 # java classes. | |
| 9 | |
| 10 """Extracts native methods from a Java file and generates the JNI bindings. | 6 """Extracts native methods from a Java file and generates the JNI bindings. |
| 11 If you change this, please run and update the tests.""" | 7 If you change this, please run and update the tests.""" |
| 12 | 8 |
| 13 import collections | 9 import collections |
| 14 import optparse | 10 import optparse |
| 15 import os | 11 import os |
| 16 import re | 12 import re |
| 17 import string | 13 import string |
| 18 from string import Template | 14 from string import Template |
| 19 import subprocess | 15 import subprocess |
| 20 import sys | 16 import sys |
| 21 import textwrap | 17 import textwrap |
| 22 import zipfile | 18 import zipfile |
| 23 | 19 |
| 24 UNKNOWN_JAVA_TYPE_PREFIX = 'UNKNOWN_JAVA_TYPE: ' | |
| 25 | |
| 26 | 20 |
| 27 class ParseError(Exception): | 21 class ParseError(Exception): |
| 28 """Exception thrown when we can't parse the input file.""" | 22 """Exception thrown when we can't parse the input file.""" |
| 29 | 23 |
| 30 def __init__(self, description, *context_lines): | 24 def __init__(self, description, *context_lines): |
| 31 Exception.__init__(self) | 25 Exception.__init__(self) |
| 32 self.description = description | 26 self.description = description |
| 33 self.context_lines = context_lines | 27 self.context_lines = context_lines |
| 34 | 28 |
| 35 def __str__(self): | 29 def __str__(self): |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 106 elif java_type in java_type_map: | 100 elif java_type in java_type_map: |
| 107 return java_type_map[java_type] | 101 return java_type_map[java_type] |
| 108 elif java_type.endswith('[]'): | 102 elif java_type.endswith('[]'): |
| 109 if java_type[:-2] in java_pod_type_map: | 103 if java_type[:-2] in java_pod_type_map: |
| 110 return java_pod_type_map[java_type[:-2]] + 'Array' | 104 return java_pod_type_map[java_type[:-2]] + 'Array' |
| 111 return 'jobjectArray' | 105 return 'jobjectArray' |
| 112 else: | 106 else: |
| 113 return 'jobject' | 107 return 'jobject' |
| 114 | 108 |
| 115 | 109 |
| 116 def JavaParamToJni(param): | 110 class JniParams(object): |
| 117 """Converts a java param into a JNI signature type.""" | 111 _UNKNOWN_JAVA_TYPE_PREFIX = 'UNKNOWN_JAVA_TYPE: ' |
| 118 pod_param_map = { | 112 _external_param_files = set() |
| 119 'int': 'I', | 113 _external_param_list = [] |
|
Nico
2012/10/31 17:41:28
Meh, that's still global state. Why not make this
bulach
2012/10/31 17:53:10
I agree, but that's a much more complex change :)
| |
| 120 'boolean': 'Z', | |
| 121 'long': 'J', | |
| 122 'double': 'D', | |
| 123 'float': 'F', | |
| 124 'byte': 'B', | |
| 125 'void': 'V', | |
| 126 } | |
| 127 object_param_list = [ | |
| 128 'Ljava/lang/Boolean', | |
| 129 'Ljava/lang/Integer', | |
| 130 'Ljava/lang/Long', | |
| 131 'Ljava/lang/Object', | |
| 132 'Ljava/lang/String', | |
| 133 'Ljava/util/ArrayList', | |
| 134 'Ljava/util/HashMap', | |
| 135 'Ljava/util/List', | |
| 136 'Landroid/content/Context', | |
| 137 'Landroid/graphics/Bitmap', | |
| 138 'Landroid/graphics/Canvas', | |
| 139 'Landroid/graphics/Rect', | |
| 140 'Landroid/graphics/RectF', | |
| 141 'Landroid/graphics/Matrix', | |
| 142 'Landroid/graphics/Point', | |
| 143 'Landroid/graphics/SurfaceTexture$OnFrameAvailableListener', | |
| 144 'Landroid/media/MediaPlayer', | |
| 145 'Landroid/os/Message', | |
| 146 'Landroid/view/KeyEvent', | |
| 147 'Landroid/view/Surface', | |
| 148 'Landroid/view/View', | |
| 149 'Landroid/webkit/ValueCallback', | |
| 150 'Ljava/io/InputStream', | |
| 151 'Ljava/nio/ByteBuffer', | |
| 152 'Ljava/util/Vector', | |
| 153 ] | |
| 154 app_param_list = [ | |
| 155 'Landroid/graphics/SurfaceTexture', | |
| 156 'Lcom/google/android/apps/chrome/ChromeContextMenuInfo', | |
| 157 'Lcom/google/android/apps/chrome/ChromeWindow', | |
| 158 'Lcom/google/android/apps/chrome/GoogleLocationSettingsHelperImpl', | |
| 159 'Lcom/google/android/apps/chrome/OmniboxSuggestion', | |
| 160 'Lcom/google/android/apps/chrome/PageInfoViewer', | |
| 161 'Lcom/google/android/apps/chrome/Tab', | |
| 162 'Lcom/google/android/apps/chrome/infobar/AutoLogin', | |
| 163 'Lcom/google/android/apps/chrome/infobar/InfoBarContainer', | |
| 164 'Lcom/google/android/apps/chrome/infobar/InfoBarContainer$NativeInfoBar', | |
| 165 ('Lcom/google/android/apps/chrome/preferences/ChromeNativePreferences$' | |
| 166 'PasswordListObserver'), | |
| 167 'Lorg/chromium/android_webview/AwContents', | |
| 168 'Lorg/chromium/android_webview/AwContentsClient', | |
| 169 'Lorg/chromium/android_webview/AwHttpAuthHandler', | |
| 170 'Lorg/chromium/android_webview/AwContentsIoThreadClient', | |
| 171 'Lorg/chromium/android_webview/AwWebContentsDelegate', | |
| 172 'Lorg/chromium/android_webview/InterceptedRequestData', | |
| 173 'Lorg/chromium/android_webview/JsPromptResultReceiver', | |
| 174 'Lorg/chromium/android_webview/JsResultHandler', | |
| 175 'Lorg/chromium/android_webview/JsResultReceiver', | |
| 176 'Lorg/chromium/base/SystemMessageHandler', | |
| 177 'Lorg/chromium/chrome/browser/autofill/AutofillExternalDelegate', | |
| 178 'Lorg/chromium/chrome/browser/autofill/AutofillSuggestion', | |
| 179 'Lorg/chromium/chrome/browser/ChromeBrowserProvider$BookmarkNode', | |
| 180 'Lorg/chromium/chrome/browser/ChromeHttpAuthHandler', | |
| 181 'Lorg/chromium/chrome/browser/ChromeWebContentsDelegateAndroid', | |
| 182 'Lorg/chromium/chrome/browser/FindMatchRectsDetails', | |
| 183 'Lorg/chromium/chrome/browser/FindNotificationDetails', | |
| 184 'Lorg/chromium/chrome/browser/GoogleLocationSettingsHelper', | |
| 185 'Lorg/chromium/chrome/browser/GoogleLocationSettingsHelperStub', | |
| 186 'Lorg/chromium/chrome/browser/JavascriptAppModalDialog', | |
| 187 'Lorg/chromium/chrome/browser/ProcessUtils', | |
| 188 ('Lorg/chromium/chrome/browser/component/navigation_interception/' | |
| 189 'InterceptNavigationDelegate'), | |
| 190 ('Lorg/chromium/chrome/browser/component/web_contents_delegate_android/' | |
| 191 'WebContentsDelegateAndroid'), | |
| 192 'Lorg/chromium/chrome/browser/database/SQLiteCursor', | |
| 193 'Lorg/chromium/content/app/SandboxedProcessService', | |
| 194 'Lorg/chromium/content/browser/ContainerViewDelegate', | |
| 195 'Lorg/chromium/content/browser/ContentVideoView', | |
| 196 'Lorg/chromium/content/browser/ContentViewCore', | |
| 197 'Lorg/chromium/content/browser/DeviceOrientation', | |
| 198 'Lorg/chromium/content/browser/JavaInputStream', | |
| 199 'Lorg/chromium/content/browser/LocationProvider', | |
| 200 'Lorg/chromium/content/browser/SandboxedProcessArgs', | |
| 201 'Lorg/chromium/content/browser/SandboxedProcessConnection', | |
| 202 'Lorg/chromium/content/browser/TouchPoint', | |
| 203 'Lorg/chromium/content/browser/WaitableNativeEvent', | |
| 204 'Lorg/chromium/content/browser/WebContentsObserverAndroid', | |
| 205 'Lorg/chromium/content/common/DeviceInfo', | |
| 206 'Lorg/chromium/content/common/SurfaceTextureListener', | |
| 207 'Lorg/chromium/media/MediaPlayerListener', | |
| 208 'Lorg/chromium/net/NetworkChangeNotifier', | |
| 209 'Lorg/chromium/net/ProxyChangeListener', | |
| 210 'Lorg/chromium/ui/gfx/NativeWindow', | |
| 211 'Lorg/chromium/ui/SelectFileDialog', | |
| 212 ] | |
| 213 if param == 'byte[][]': | |
| 214 return '[[B' | |
| 215 prefix = '' | |
| 216 # Array? | |
| 217 if param[-2:] == '[]': | |
| 218 prefix = '[' | |
| 219 param = param[:-2] | |
| 220 # Generic? | |
| 221 if '<' in param: | |
| 222 param = param[:param.index('<')] | |
| 223 if param in pod_param_map: | |
| 224 return prefix + pod_param_map[param] | |
| 225 if '/' in param: | |
| 226 # Coming from javap, use the fully qualified param directly. | |
| 227 return 'L' + param + ';' | |
| 228 for qualified_name in object_param_list + app_param_list: | |
| 229 if (qualified_name.endswith('/' + param) or | |
| 230 qualified_name.endswith('$' + param.replace('.', '$')) or | |
| 231 qualified_name == 'L' + param): | |
| 232 return prefix + qualified_name + ';' | |
| 233 else: | |
| 234 return UNKNOWN_JAVA_TYPE_PREFIX + prefix + param + ';' | |
| 235 | 114 |
| 115 @staticmethod | |
| 116 def ReadExternalParamList(external_param_files): | |
| 117 if not external_param_files: | |
| 118 return | |
| 119 assert not JniParams._external_param_files | |
| 120 JniParams._external_param_files = set(external_param_files) | |
| 121 for external_param_file in JniParams._external_param_files: | |
| 122 with file(external_param_file, 'r') as f: | |
| 123 contents = f.read() | |
| 124 JniParams._external_param_list += [x.strip() | |
| 125 for x in contents.splitlines() | |
| 126 if x and not x.startswith('#')] | |
| 236 | 127 |
| 237 def JniSignature(params, returns, wrap): | 128 @staticmethod |
| 238 """Returns the JNI signature for the given datatypes.""" | 129 def JavaToJni(param): |
| 239 items = ['('] | 130 """Converts a java param into a JNI signature type.""" |
| 240 items += [JavaParamToJni(param.datatype) for param in params] | 131 pod_param_map = { |
| 241 items += [')'] | 132 'int': 'I', |
| 242 items += [JavaParamToJni(returns)] | 133 'boolean': 'Z', |
| 243 if wrap: | 134 'long': 'J', |
| 244 return '\n' + '\n'.join(['"' + item + '"' for item in items]) | 135 'double': 'D', |
| 245 else: | 136 'float': 'F', |
| 246 return '"' + ''.join(items) + '"' | 137 'byte': 'B', |
| 138 'void': 'V', | |
| 139 } | |
| 140 object_param_list = [ | |
| 141 'Ljava/lang/Boolean', | |
| 142 'Ljava/lang/Integer', | |
| 143 'Ljava/lang/Long', | |
| 144 'Ljava/lang/Object', | |
| 145 'Ljava/lang/String', | |
| 146 'Ljava/util/ArrayList', | |
| 147 'Ljava/util/HashMap', | |
| 148 'Ljava/util/List', | |
| 149 'Landroid/content/Context', | |
| 150 'Landroid/graphics/Bitmap', | |
| 151 'Landroid/graphics/Canvas', | |
| 152 'Landroid/graphics/Rect', | |
| 153 'Landroid/graphics/RectF', | |
| 154 'Landroid/graphics/Matrix', | |
| 155 'Landroid/graphics/Point', | |
| 156 'Landroid/graphics/SurfaceTexture', | |
| 157 'Landroid/graphics/SurfaceTexture$OnFrameAvailableListener', | |
| 158 'Landroid/media/MediaPlayer', | |
| 159 'Landroid/os/Message', | |
| 160 'Landroid/view/KeyEvent', | |
| 161 'Landroid/view/Surface', | |
| 162 'Landroid/view/View', | |
| 163 'Landroid/webkit/ValueCallback', | |
| 164 'Ljava/io/InputStream', | |
| 165 'Ljava/nio/ByteBuffer', | |
| 166 'Ljava/util/Vector', | |
| 167 ] | |
| 168 if param == 'byte[][]': | |
| 169 return '[[B' | |
| 170 prefix = '' | |
| 171 # Array? | |
| 172 if param[-2:] == '[]': | |
| 173 prefix = '[' | |
| 174 param = param[:-2] | |
| 175 # Generic? | |
| 176 if '<' in param: | |
| 177 param = param[:param.index('<')] | |
| 178 if param in pod_param_map: | |
| 179 return prefix + pod_param_map[param] | |
| 180 if '/' in param: | |
| 181 # Coming from javap, use the fully qualified param directly. | |
| 182 return 'L' + param + ';' | |
| 183 for qualified_name in object_param_list + JniParams._external_param_list: | |
| 184 if (qualified_name.endswith('/' + param) or | |
| 185 qualified_name.endswith('$' + param.replace('.', '$')) or | |
| 186 qualified_name == 'L' + param): | |
| 187 return prefix + qualified_name + ';' | |
| 188 else: | |
| 189 return JniParams._UNKNOWN_JAVA_TYPE_PREFIX + prefix + param + ';' | |
| 247 | 190 |
| 191 @staticmethod | |
| 192 def Signature(params, returns, wrap): | |
| 193 """Returns the JNI signature for the given datatypes.""" | |
| 194 items = ['('] | |
| 195 items += [JniParams.JavaToJni(param.datatype) for param in params] | |
| 196 items += [')'] | |
| 197 items += [JniParams.JavaToJni(returns)] | |
| 198 if wrap: | |
| 199 return '\n' + '\n'.join(['"' + item + '"' for item in items]) | |
| 200 else: | |
| 201 return '"' + ''.join(items) + '"' | |
| 248 | 202 |
| 249 def ParseParams(params): | 203 @staticmethod |
| 250 """Parses the params into a list of Param objects.""" | 204 def Parse(params): |
| 251 if not params: | 205 """Parses the params into a list of Param objects.""" |
| 252 return [] | 206 if not params: |
| 253 ret = [] | 207 return [] |
| 254 for p in [p.strip() for p in params.split(',')]: | 208 ret = [] |
| 255 items = p.split(' ') | 209 for p in [p.strip() for p in params.split(',')]: |
| 256 if 'final' in items: | 210 items = p.split(' ') |
| 257 items.remove('final') | 211 if 'final' in items: |
| 258 param = Param( | 212 items.remove('final') |
| 259 datatype=items[0], | 213 param = Param( |
| 260 name=(items[1] if len(items) > 1 else 'p%s' % len(ret)), | 214 datatype=items[0], |
| 261 ) | 215 name=(items[1] if len(items) > 1 else 'p%s' % len(ret)), |
| 262 ret += [param] | 216 ) |
| 263 return ret | 217 ret += [param] |
| 218 return ret | |
| 264 | 219 |
| 220 @staticmethod | |
| 221 def CheckUnknownDatatypes(fully_qualified_class, items): | |
| 222 unknown_datatypes = JniParams._GetUnknownDatatypes(items) | |
| 223 if unknown_datatypes: | |
| 224 msg = ('There are a few unknown datatypes in %s' % | |
| 225 fully_qualified_class) | |
| 226 msg += '\nPlease, edit %s' % str(JniParams._external_param_files) | |
| 227 msg += '\nand add the JNI type(s):\n' | |
| 228 for unknown_datatype in unknown_datatypes: | |
| 229 msg += '\n%s in methods:\n' % unknown_datatype | |
| 230 msg += '\n '.join(unknown_datatypes[unknown_datatype]) | |
| 231 raise SyntaxError(msg) | |
| 265 | 232 |
| 266 def GetUnknownDatatypes(items): | 233 @staticmethod |
| 267 """Returns a list containing the unknown datatypes.""" | 234 def _GetUnknownDatatypes(items): |
| 268 unknown_types = {} | 235 """Returns a list containing the unknown datatypes.""" |
| 269 for item in items: | 236 unknown_types = {} |
| 270 all_datatypes = ([JavaParamToJni(param.datatype) | 237 for item in items: |
| 271 for param in item.params] + | 238 all_datatypes = ([JniParams.JavaToJni(param.datatype) |
| 272 [JavaParamToJni(item.return_type)]) | 239 for param in item.params] + |
| 273 for d in all_datatypes: | 240 [JniParams.JavaToJni(item.return_type)]) |
| 274 if d.startswith(UNKNOWN_JAVA_TYPE_PREFIX): | 241 for d in all_datatypes: |
| 275 unknown_types[d] = (unknown_types.get(d, []) + | 242 if d.startswith(JniParams._UNKNOWN_JAVA_TYPE_PREFIX): |
| 276 [item.name or 'Unable to parse']) | 243 unknown_types[d] = (unknown_types.get(d, []) + |
| 277 return unknown_types | 244 [item.name or 'Unable to parse']) |
| 245 return unknown_types | |
| 278 | 246 |
| 279 | 247 |
| 280 def ExtractJNINamespace(contents): | 248 def ExtractJNINamespace(contents): |
| 281 re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)') | 249 re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)') |
| 282 m = re.findall(re_jni_namespace, contents) | 250 m = re.findall(re_jni_namespace, contents) |
| 283 if not m: | 251 if not m: |
| 284 return '' | 252 return '' |
| 285 return m[0] | 253 return m[0] |
| 286 | 254 |
| 287 | 255 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 304 '(?P<qualifiers>\w+\s\w+|\w+|\s+)\s*?native ' | 272 '(?P<qualifiers>\w+\s\w+|\w+|\s+)\s*?native ' |
| 305 '(?P<return>\S*?) ' | 273 '(?P<return>\S*?) ' |
| 306 '(?P<name>\w+?)\((?P<params>.*?)\);') | 274 '(?P<name>\w+?)\((?P<params>.*?)\);') |
| 307 for match in re.finditer(re_native, contents): | 275 for match in re.finditer(re_native, contents): |
| 308 native = NativeMethod( | 276 native = NativeMethod( |
| 309 static='static' in match.group('qualifiers'), | 277 static='static' in match.group('qualifiers'), |
| 310 java_class_name=match.group('java_class_name'), | 278 java_class_name=match.group('java_class_name'), |
| 311 native_class_name=match.group('native_class_name'), | 279 native_class_name=match.group('native_class_name'), |
| 312 return_type=match.group('return'), | 280 return_type=match.group('return'), |
| 313 name=match.group('name').replace('native', ''), | 281 name=match.group('name').replace('native', ''), |
| 314 params=ParseParams(match.group('params'))) | 282 params=JniParams.Parse(match.group('params'))) |
| 315 natives += [native] | 283 natives += [native] |
| 316 return natives | 284 return natives |
| 317 | 285 |
| 318 | 286 |
| 319 def GetStaticCastForReturnType(return_type): | 287 def GetStaticCastForReturnType(return_type): |
| 320 if return_type == 'String': | 288 if return_type == 'String': |
| 321 return 'jstring' | 289 return 'jstring' |
| 322 return None | 290 return None |
| 323 | 291 |
| 324 | 292 |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 366 Args: | 334 Args: |
| 367 name: string. | 335 name: string. |
| 368 params: list of Param. | 336 params: list of Param. |
| 369 return_type: string. | 337 return_type: string. |
| 370 | 338 |
| 371 Returns: | 339 Returns: |
| 372 A mangled name. | 340 A mangled name. |
| 373 """ | 341 """ |
| 374 mangled_items = [] | 342 mangled_items = [] |
| 375 for datatype in [return_type] + [x.datatype for x in params]: | 343 for datatype in [return_type] + [x.datatype for x in params]: |
| 376 mangled_items += [GetMangledParam(JavaParamToJni(datatype))] | 344 mangled_items += [GetMangledParam(JniParams.JavaToJni(datatype))] |
| 377 mangled_name = name + '_'.join(mangled_items) | 345 mangled_name = name + '_'.join(mangled_items) |
| 378 assert re.match(r'[0-9a-zA-Z_]+', mangled_name) | 346 assert re.match(r'[0-9a-zA-Z_]+', mangled_name) |
| 379 return mangled_name | 347 return mangled_name |
| 380 | 348 |
| 381 | 349 |
| 382 def MangleCalledByNatives(called_by_natives): | 350 def MangleCalledByNatives(called_by_natives): |
| 383 """Mangles all the overloads from the call_by_natives list.""" | 351 """Mangles all the overloads from the call_by_natives list.""" |
| 384 method_counts = collections.defaultdict( | 352 method_counts = collections.defaultdict( |
| 385 lambda: collections.defaultdict(lambda: 0)) | 353 lambda: collections.defaultdict(lambda: 0)) |
| 386 for called_by_native in called_by_natives: | 354 for called_by_native in called_by_natives: |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 """ | 395 """ |
| 428 called_by_natives = [] | 396 called_by_natives = [] |
| 429 for match in re.finditer(RE_CALLED_BY_NATIVE, contents): | 397 for match in re.finditer(RE_CALLED_BY_NATIVE, contents): |
| 430 called_by_natives += [CalledByNative( | 398 called_by_natives += [CalledByNative( |
| 431 system_class=False, | 399 system_class=False, |
| 432 unchecked='Unchecked' in match.group('Unchecked'), | 400 unchecked='Unchecked' in match.group('Unchecked'), |
| 433 static='static' in match.group('prefix'), | 401 static='static' in match.group('prefix'), |
| 434 java_class_name=match.group('annotation') or '', | 402 java_class_name=match.group('annotation') or '', |
| 435 return_type=match.group('return_type'), | 403 return_type=match.group('return_type'), |
| 436 name=match.group('name'), | 404 name=match.group('name'), |
| 437 params=ParseParams(match.group('params')))] | 405 params=JniParams.Parse(match.group('params')))] |
| 438 # Check for any @CalledByNative occurrences that weren't matched. | 406 # Check for any @CalledByNative occurrences that weren't matched. |
| 439 unmatched_lines = re.sub(RE_CALLED_BY_NATIVE, '', contents).split('\n') | 407 unmatched_lines = re.sub(RE_CALLED_BY_NATIVE, '', contents).split('\n') |
| 440 for line1, line2 in zip(unmatched_lines, unmatched_lines[1:]): | 408 for line1, line2 in zip(unmatched_lines, unmatched_lines[1:]): |
| 441 if '@CalledByNative' in line1: | 409 if '@CalledByNative' in line1: |
| 442 raise ParseError('could not parse @CalledByNative method signature', | 410 raise ParseError('could not parse @CalledByNative method signature', |
| 443 line1, line2) | 411 line1, line2) |
| 444 return MangleCalledByNatives(called_by_natives) | 412 return MangleCalledByNatives(called_by_natives) |
| 445 | 413 |
| 446 | 414 |
| 447 class JNIFromJavaP(object): | 415 class JNIFromJavaP(object): |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 463 match = re.match(re_method, content) | 431 match = re.match(re_method, content) |
| 464 if not match: | 432 if not match: |
| 465 continue | 433 continue |
| 466 self.called_by_natives += [CalledByNative( | 434 self.called_by_natives += [CalledByNative( |
| 467 system_class=True, | 435 system_class=True, |
| 468 unchecked=False, | 436 unchecked=False, |
| 469 static='static' in match.group('prefix'), | 437 static='static' in match.group('prefix'), |
| 470 java_class_name='', | 438 java_class_name='', |
| 471 return_type=match.group('return_type'), | 439 return_type=match.group('return_type'), |
| 472 name=match.group('name'), | 440 name=match.group('name'), |
| 473 params=ParseParams(match.group('params').replace('.', '/')))] | 441 params=JniParams.Parse(match.group('params').replace('.', '/')))] |
| 474 re_constructor = re.compile('.*? public ' + | 442 re_constructor = re.compile('.*? public ' + |
| 475 self.fully_qualified_class.replace('/', '.') + | 443 self.fully_qualified_class.replace('/', '.') + |
| 476 '\((?P<params>.*?)\)') | 444 '\((?P<params>.*?)\)') |
| 477 for content in contents[2:]: | 445 for content in contents[2:]: |
| 478 match = re.match(re_constructor, content) | 446 match = re.match(re_constructor, content) |
| 479 if not match: | 447 if not match: |
| 480 continue | 448 continue |
| 481 self.called_by_natives += [CalledByNative( | 449 self.called_by_natives += [CalledByNative( |
| 482 system_class=True, | 450 system_class=True, |
| 483 unchecked=False, | 451 unchecked=False, |
| 484 static=False, | 452 static=False, |
| 485 java_class_name='', | 453 java_class_name='', |
| 486 return_type=self.fully_qualified_class, | 454 return_type=self.fully_qualified_class, |
| 487 name='Constructor', | 455 name='Constructor', |
| 488 params=ParseParams(match.group('params').replace('.', '/')), | 456 params=JniParams.Parse(match.group('params').replace('.', '/')), |
| 489 is_constructor=True)] | 457 is_constructor=True)] |
| 490 self.called_by_natives = MangleCalledByNatives(self.called_by_natives) | 458 self.called_by_natives = MangleCalledByNatives(self.called_by_natives) |
| 491 self.inl_header_file_generator = InlHeaderFileGenerator( | 459 self.inl_header_file_generator = InlHeaderFileGenerator( |
| 492 self.namespace, self.fully_qualified_class, [], self.called_by_natives) | 460 self.namespace, self.fully_qualified_class, [], self.called_by_natives) |
| 493 | 461 |
| 494 def GetContent(self): | 462 def GetContent(self): |
| 495 return self.inl_header_file_generator.GetContent() | 463 return self.inl_header_file_generator.GetContent() |
| 496 | 464 |
| 497 @staticmethod | 465 @staticmethod |
| 498 def CreateFromClass(class_file, namespace): | 466 def CreateFromClass(class_file, namespace): |
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 554 """Generates an inline header file for JNI integration.""" | 522 """Generates an inline header file for JNI integration.""" |
| 555 | 523 |
| 556 def __init__(self, namespace, fully_qualified_class, natives, | 524 def __init__(self, namespace, fully_qualified_class, natives, |
| 557 called_by_natives): | 525 called_by_natives): |
| 558 self.namespace = namespace | 526 self.namespace = namespace |
| 559 self.fully_qualified_class = fully_qualified_class | 527 self.fully_qualified_class = fully_qualified_class |
| 560 self.class_name = self.fully_qualified_class.split('/')[-1] | 528 self.class_name = self.fully_qualified_class.split('/')[-1] |
| 561 self.natives = natives | 529 self.natives = natives |
| 562 self.called_by_natives = called_by_natives | 530 self.called_by_natives = called_by_natives |
| 563 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' | 531 self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' |
| 564 unknown_datatypes = GetUnknownDatatypes(self.natives + | 532 JniParams.CheckUnknownDatatypes(self.fully_qualified_class, |
| 565 self.called_by_natives) | 533 self.natives + self.called_by_natives) |
| 566 if unknown_datatypes: | |
| 567 msg = ('There are a few unknown datatypes in %s' % | |
| 568 self.fully_qualified_class) | |
| 569 msg += '\nPlease, edit %s' % sys.argv[0] | |
| 570 msg += '\nand add the java type to JavaParamToJni()\n' | |
| 571 for unknown_datatype in unknown_datatypes: | |
| 572 msg += '\n%s in methods:\n' % unknown_datatype | |
| 573 msg += '\n '.join(unknown_datatypes[unknown_datatype]) | |
| 574 raise SyntaxError(msg) | |
| 575 | 534 |
| 576 def GetContent(self): | 535 def GetContent(self): |
| 577 """Returns the content of the JNI binding file.""" | 536 """Returns the content of the JNI binding file.""" |
| 578 template = Template("""\ | 537 template = Template("""\ |
| 579 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 538 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 580 // Use of this source code is governed by a BSD-style license that can be | 539 // Use of this source code is governed by a BSD-style license that can be |
| 581 // found in the LICENSE file. | 540 // found in the LICENSE file. |
| 582 | 541 |
| 583 | 542 |
| 584 // This file is autogenerated by | 543 // This file is autogenerated by |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 858 values['FUNCTION_HEADER'] = ( | 817 values['FUNCTION_HEADER'] = ( |
| 859 function_header_with_unused_template.substitute(values)) | 818 function_header_with_unused_template.substitute(values)) |
| 860 else: | 819 else: |
| 861 values['FUNCTION_HEADER'] = function_header_template.substitute(values) | 820 values['FUNCTION_HEADER'] = function_header_template.substitute(values) |
| 862 return template.substitute(values) | 821 return template.substitute(values) |
| 863 | 822 |
| 864 def GetKMethodArrayEntry(self, native): | 823 def GetKMethodArrayEntry(self, native): |
| 865 template = Template("""\ | 824 template = Template("""\ |
| 866 { "native${NAME}", ${JNI_SIGNATURE}, reinterpret_cast<void*>(${NAME}) },""") | 825 { "native${NAME}", ${JNI_SIGNATURE}, reinterpret_cast<void*>(${NAME}) },""") |
| 867 values = {'NAME': native.name, | 826 values = {'NAME': native.name, |
| 868 'JNI_SIGNATURE': JniSignature(native.params, native.return_type, | 827 'JNI_SIGNATURE': JniParams.Signature(native.params, |
| 869 True)} | 828 native.return_type, |
| 829 True)} | |
| 870 return template.substitute(values) | 830 return template.substitute(values) |
| 871 | 831 |
| 872 def GetUniqueClasses(self, origin): | 832 def GetUniqueClasses(self, origin): |
| 873 ret = {self.class_name: self.fully_qualified_class} | 833 ret = {self.class_name: self.fully_qualified_class} |
| 874 for entry in origin: | 834 for entry in origin: |
| 875 class_name = self.class_name | 835 class_name = self.class_name |
| 876 jni_class_path = self.fully_qualified_class | 836 jni_class_path = self.fully_qualified_class |
| 877 if entry.java_class_name: | 837 if entry.java_class_name: |
| 878 class_name = entry.java_class_name | 838 class_name = entry.java_class_name |
| 879 jni_class_path = self.fully_qualified_class + '$' + class_name | 839 jni_class_path = self.fully_qualified_class + '$' + class_name |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 930 jni_name = called_by_native.name | 890 jni_name = called_by_native.name |
| 931 jni_return_type = called_by_native.return_type | 891 jni_return_type = called_by_native.return_type |
| 932 if called_by_native.is_constructor: | 892 if called_by_native.is_constructor: |
| 933 jni_name = '<init>' | 893 jni_name = '<init>' |
| 934 jni_return_type = 'void' | 894 jni_return_type = 'void' |
| 935 values = { | 895 values = { |
| 936 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, | 896 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, |
| 937 'JNI_NAME': jni_name, | 897 'JNI_NAME': jni_name, |
| 938 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, | 898 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, |
| 939 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', | 899 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', |
| 940 'JNI_SIGNATURE': JniSignature(called_by_native.params, | 900 'JNI_SIGNATURE': JniParams.Signature(called_by_native.params, |
| 941 jni_return_type, | 901 jni_return_type, |
| 942 True) | 902 True) |
| 943 } | 903 } |
| 944 return template.substitute(values) | 904 return template.substitute(values) |
| 945 | 905 |
| 946 | 906 |
| 947 def WrapOutput(output): | 907 def WrapOutput(output): |
| 948 ret = [] | 908 ret = [] |
| 949 for line in output.splitlines(): | 909 for line in output.splitlines(): |
| 950 # Do not wrap lines under 80 characters or preprocessor directives. | 910 # Do not wrap lines under 80 characters or preprocessor directives. |
| 951 if len(line) < 80 or line.lstrip()[:1] == '#': | 911 if len(line) < 80 or line.lstrip()[:1] == '#': |
| 952 stripped = line.rstrip() | 912 stripped = line.rstrip() |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1027 option_parser.add_option('-n', dest='namespace', | 987 option_parser.add_option('-n', dest='namespace', |
| 1028 help='Uses as a namespace in the generated header,' | 988 help='Uses as a namespace in the generated header,' |
| 1029 ' instead of the javap class name.') | 989 ' instead of the javap class name.') |
| 1030 option_parser.add_option('--input_file', | 990 option_parser.add_option('--input_file', |
| 1031 help='Single input file name. The output file name ' | 991 help='Single input file name. The output file name ' |
| 1032 'will be derived from it. Must be used with ' | 992 'will be derived from it. Must be used with ' |
| 1033 '--output_dir.') | 993 '--output_dir.') |
| 1034 option_parser.add_option('--output_dir', | 994 option_parser.add_option('--output_dir', |
| 1035 help='The output directory. Must be used with ' | 995 help='The output directory. Must be used with ' |
| 1036 '--input') | 996 '--input') |
| 997 option_parser.add_option('--external_param_list', | |
| 998 help='A file name containing a list with extra ' | |
| 999 'fully-qualified param names. Can be used multiple ' | |
| 1000 'times.', | |
| 1001 action='append') | |
| 1037 options, args = option_parser.parse_args(argv) | 1002 options, args = option_parser.parse_args(argv) |
| 1003 JniParams.ReadExternalParamList(options.external_param_list) | |
| 1038 if options.jar_file: | 1004 if options.jar_file: |
| 1039 input_file = ExtractJarInputFile(options.jar_file, options.input_file, | 1005 input_file = ExtractJarInputFile(options.jar_file, options.input_file, |
| 1040 options.output_dir) | 1006 options.output_dir) |
| 1041 else: | 1007 else: |
| 1042 input_file = options.input_file | 1008 input_file = options.input_file |
| 1043 output_file = None | 1009 output_file = None |
| 1044 if options.output_dir: | 1010 if options.output_dir: |
| 1045 root_name = os.path.splitext(os.path.basename(input_file))[0] | 1011 root_name = os.path.splitext(os.path.basename(input_file))[0] |
| 1046 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' | 1012 output_file = os.path.join(options.output_dir, root_name) + '_jni.h' |
| 1047 GenerateJNIHeader(input_file, output_file, options.namespace) | 1013 GenerateJNIHeader(input_file, output_file, options.namespace) |
| 1048 | 1014 |
| 1049 | 1015 |
| 1050 if __name__ == '__main__': | 1016 if __name__ == '__main__': |
| 1051 sys.exit(main(sys.argv)) | 1017 sys.exit(main(sys.argv)) |
| OLD | NEW |