15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/env python 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Extracts native methods from a Java file and generates the JNI bindings. 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)If you change this, please run and update the tests.""" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import collections 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)import errno 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import optparse 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import string 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from string import Template 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import subprocess 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import textwrap 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import zipfile 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 21116680a4aac90f2aa7413d9095a592090648e557Ben MurdochCHROMIUM_SRC = os.path.join( 22116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch os.path.dirname(__file__), os.pardir, os.pardir, os.pardir) 23116680a4aac90f2aa7413d9095a592090648e557Ben MurdochBUILD_ANDROID_GYP = os.path.join( 24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch CHROMIUM_SRC, 'build', 'android', 'gyp') 25116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 26116680a4aac90f2aa7413d9095a592090648e557Ben Murdochsys.path.append(BUILD_ANDROID_GYP) 27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 28116680a4aac90f2aa7413d9095a592090648e557Ben Murdochfrom util import build_utils 29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ParseError(Exception): 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Exception thrown when we can't parse the input file.""" 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, description, *context_lines): 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Exception.__init__(self) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.description = description 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.context_lines = context_lines 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __str__(self): 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) context = '\n'.join(self.context_lines) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '***\nERROR: %s\n\n%s\n***' % (self.description, context) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Param(object): 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Describes a param for a method, either java or native.""" 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, **kwargs): 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.datatype = kwargs['datatype'] 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.name = kwargs['name'] 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class NativeMethod(object): 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Describes a C/C++ method that is called by Java code""" 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, **kwargs): 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.static = kwargs['static'] 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.java_class_name = kwargs['java_class_name'] 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.return_type = kwargs['return_type'] 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.name = kwargs['name'] 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.params = kwargs['params'] 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.params: 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert type(self.params) is list 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert type(self.params[0]) is Param 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (self.params and 650f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) self.params[0].datatype == kwargs.get('ptr_type', 'int') and 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.params[0].name.startswith('native')): 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.type = 'method' 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.p0_type = self.params[0].name[len('native'):] 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if kwargs.get('native_class_name'): 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.p0_type = kwargs['native_class_name'] 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.type = 'function' 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.method_id_var_name = kwargs.get('method_id_var_name', None) 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class CalledByNative(object): 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Describes a java method exported to c/c++""" 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, **kwargs): 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.system_class = kwargs['system_class'] 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.unchecked = kwargs['unchecked'] 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.static = kwargs['static'] 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.java_class_name = kwargs['java_class_name'] 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.return_type = kwargs['return_type'] 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.name = kwargs['name'] 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.params = kwargs['params'] 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.method_id_var_name = kwargs.get('method_id_var_name', None) 881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) self.signature = kwargs.get('signature') 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.is_constructor = kwargs.get('is_constructor', False) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.env_call = GetEnvCall(self.is_constructor, self.static, 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.return_type) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.static_cast = GetStaticCastForReturnType(self.return_type) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)class ConstantField(object): 96a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) def __init__(self, **kwargs): 97a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) self.name = kwargs['name'] 98a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) self.value = kwargs['value'] 99a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 100a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def JavaDataTypeToC(java_type): 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns a C datatype for the given java type.""" 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_pod_type_map = { 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'int': 'jint', 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'byte': 'jbyte', 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'char': 'jchar', 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'short': 'jshort', 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'boolean': 'jboolean', 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'long': 'jlong', 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'double': 'jdouble', 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'float': 'jfloat', 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_type_map = { 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'void': 'void', 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'String': 'jstring', 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'java/lang/String': 'jstring', 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'java/lang/Class': 'jclass', 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if java_type in java_pod_type_map: 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return java_pod_type_map[java_type] 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif java_type in java_type_map: 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return java_type_map[java_type] 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif java_type.endswith('[]'): 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if java_type[:-2] in java_pod_type_map: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return java_pod_type_map[java_type[:-2]] + 'Array' 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'jobjectArray' 1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) elif java_type.startswith('Class'): 1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # Checking just the start of the name, rather than a direct comparison, 1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) # in order to handle generics. 1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return 'jclass' 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'jobject' 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)def JavaDataTypeToCForCalledByNativeParam(java_type): 137010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) """Returns a C datatype to be when calling from native.""" 138010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if java_type == 'int': 139010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return 'JniIntWrapper' 140010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) else: 141010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return JavaDataTypeToC(java_type) 142010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 143010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)def JavaReturnValueToC(java_type): 1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Returns a valid C return value for the given java type.""" 1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) java_pod_type_map = { 1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'int': '0', 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'byte': '0', 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'char': '0', 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'short': '0', 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'boolean': 'false', 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'long': '0', 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'double': '0', 1545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'float': '0', 1555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'void': '' 1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return java_pod_type_map.get(java_type, 'NULL') 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class JniParams(object): 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _imports = [] 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _fully_qualified_class = '' 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _package = '' 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) _inner_classes = [] 165868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) _remappings = [] 166010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) _implicit_imports = [] 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @staticmethod 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def SetFullyQualifiedClass(fully_qualified_class): 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JniParams._fully_qualified_class = 'L' + fully_qualified_class 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JniParams._package = '/'.join(fully_qualified_class.split('/')[:-1]) 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @staticmethod 174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) def AddAdditionalImport(class_name): 175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) assert class_name.endswith('.class') 176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raw_class_name = class_name[:-len('.class')] 177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if '.' in raw_class_name: 178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise SyntaxError('%s cannot be used in @JNIAdditionalImport. ' 179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'Only import unqualified outer classes.' % class_name) 180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) new_import = 'L%s/%s' % (JniParams._package, raw_class_name) 181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if new_import in JniParams._imports: 182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise SyntaxError('Do not use JNIAdditionalImport on an already ' 183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'imported class: %s' % (new_import.replace('/', '.'))) 184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) JniParams._imports += [new_import] 185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) @staticmethod 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def ExtractImportsAndInnerClasses(contents): 188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if not JniParams._package: 189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) raise RuntimeError('SetFullyQualifiedClass must be called before ' 190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 'ExtractImportsAndInnerClasses') 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents = contents.replace('\n', '') 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) re_import = re.compile(r'import.*?(?P<class>\S*?);') 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for match in re.finditer(re_import, contents): 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JniParams._imports += ['L' + match.group('class').replace('.', '/')] 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) re_inner = re.compile(r'(class|interface)\s+?(?P<name>\w+?)\W') 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for match in re.finditer(re_inner, contents): 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inner = match.group('name') 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not JniParams._fully_qualified_class.endswith(inner): 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JniParams._inner_classes += [JniParams._fully_qualified_class + '$' + 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inner] 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) re_additional_imports = re.compile( 204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) r'@JNIAdditionalImport\(\s*{?(?P<class_names>.*?)}?\s*\)') 205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for match in re.finditer(re_additional_imports, contents): 206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) for class_name in match.group('class_names').split(','): 207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) JniParams.AddAdditionalImport(class_name.strip()) 208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @staticmethod 2101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) def ParseJavaPSignature(signature_line): 2111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) prefix = 'Signature: ' 2121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return '"%s"' % signature_line[signature_line.index(prefix) + len(prefix):] 2131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) @staticmethod 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def JavaToJni(param): 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Converts a java param into a JNI signature type.""" 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pod_param_map = { 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'int': 'I', 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'boolean': 'Z', 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'char': 'C', 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'short': 'S', 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'long': 'J', 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'double': 'D', 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'float': 'F', 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'byte': 'B', 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'void': 'V', 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) object_param_list = [ 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Ljava/lang/Boolean', 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Ljava/lang/Integer', 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Ljava/lang/Long', 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Ljava/lang/Object', 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Ljava/lang/String', 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'Ljava/lang/Class', 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ] 236010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefix = '' 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Array? 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while param[-2:] == '[]': 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) prefix += '[' 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) param = param[:-2] 2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Generic? 2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if '<' in param: 2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) param = param[:param.index('<')] 2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if param in pod_param_map: 2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return prefix + pod_param_map[param] 2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if '/' in param: 2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Coming from javap, use the fully qualified param directly. 249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return prefix + 'L' + JniParams.RemapClassName(param) + ';' 250effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for qualified_name in (object_param_list + 2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [JniParams._fully_qualified_class] + 2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JniParams._inner_classes): 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (qualified_name.endswith('/' + param) or 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) qualified_name.endswith('$' + param.replace('.', '$')) or 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) qualified_name == 'L' + param): 257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return prefix + JniParams.RemapClassName(qualified_name) + ';' 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Is it from an import? (e.g. referecing Class from import pkg.Class; 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # note that referencing an inner class Inner from import pkg.Class.Inner 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # is not supported). 2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for qualified_name in JniParams._imports: 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if qualified_name.endswith('/' + param): 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Ensure it's not an inner class. 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) components = qualified_name.split('/') 2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if len(components) > 2 and components[-2][0].isupper(): 2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise SyntaxError('Inner class (%s) can not be imported ' 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'and used by JNI (%s). Please import the outer ' 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'class and use Outer.Inner instead.' % 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (qualified_name, param)) 271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return prefix + JniParams.RemapClassName(qualified_name) + ';' 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Is it an inner class from an outer class import? (e.g. referencing 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) # Class.Inner from import pkg.Class). 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if '.' in param: 2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) components = param.split('.') 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) outer = '/'.join(components[:-1]) 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) inner = components[-1] 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for qualified_name in JniParams._imports: 2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if qualified_name.endswith('/' + outer): 281868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return (prefix + JniParams.RemapClassName(qualified_name) + 282868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) '$' + inner + ';') 283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch raise SyntaxError('Inner class (%s) can not be ' 284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 'used directly by JNI. Please import the outer ' 285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 'class, probably:\n' 286effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 'import %s.%s;' % 287effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch (param, JniParams._package.replace('/', '.'), 288effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch outer.replace('/', '.'))) 2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 290010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) JniParams._CheckImplicitImports(param) 291010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Type not found, falling back to same package as this class. 293868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return (prefix + 'L' + 294868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) JniParams.RemapClassName(JniParams._package + '/' + param) + ';') 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @staticmethod 297010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) def _CheckImplicitImports(param): 298010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) # Ensure implicit imports, such as java.lang.*, are not being treated 299010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) # as being in the same package. 300010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if not JniParams._implicit_imports: 301010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) # This file was generated from android.jar and lists 302010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) # all classes that are implicitly imported. 303010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) with file(os.path.join(os.path.dirname(sys.argv[0]), 304010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 'android_jar.classes'), 'r') as f: 305010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) JniParams._implicit_imports = f.readlines() 306010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for implicit_import in JniParams._implicit_imports: 307010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) implicit_import = implicit_import.strip().replace('.class', '') 308010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) implicit_import = implicit_import.replace('/', '.') 309010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if implicit_import.endswith('.' + param): 310010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) raise SyntaxError('Ambiguous class (%s) can not be used directly ' 311010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 'by JNI.\nPlease import it, probably:\n\n' 312010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 'import %s;' % 313010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) (param, implicit_import)) 314010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 315010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 316010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) @staticmethod 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Signature(params, returns, wrap): 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns the JNI signature for the given datatypes.""" 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items = ['('] 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items += [JniParams.JavaToJni(param.datatype) for param in params] 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items += [')'] 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items += [JniParams.JavaToJni(returns)] 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if wrap: 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n' + '\n'.join(['"' + item + '"' for item in items]) 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '"' + ''.join(items) + '"' 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @staticmethod 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Parse(params): 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Parses the params into a list of Param objects.""" 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not params: 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return [] 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = [] 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for p in [p.strip() for p in params.split(',')]: 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items = p.split(' ') 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if 'final' in items: 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) items.remove('final') 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) param = Param( 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) datatype=items[0], 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name=(items[1] if len(items) > 1 else 'p%s' % len(ret)), 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += [param] 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) @staticmethod 346868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) def RemapClassName(class_name): 347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) """Remaps class names using the jarjar mapping table.""" 348868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for old, new in JniParams._remappings: 3496d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if old.endswith('**') and old[:-2] in class_name: 3506d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return class_name.replace(old[:-2], new, 1) 3516d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if '*' not in old and class_name.endswith(old): 352868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return class_name.replace(old, new, 1) 3536d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 354868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return class_name 355868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 356868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) @staticmethod 357868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) def SetJarJarMappings(mappings): 358868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) """Parse jarjar mappings from a string.""" 359868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) JniParams._remappings = [] 360868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) for line in mappings.splitlines(): 3616d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) rule = line.split() 3626d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if rule[0] != 'rule': 363868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) continue 3646d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) _, src, dest = rule 3656d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) src = src.replace('.', '/') 366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) dest = dest.replace('.', '/') 3676d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if src.endswith('**'): 3686d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) src_real_name = src[:-2] 369868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) else: 3706d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) assert not '*' in src 3716d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) src_real_name = src 3726d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 3736d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) if dest.endswith('@0'): 3746d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) JniParams._remappings.append((src, dest[:-2] + src_real_name)) 3756d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) elif dest.endswith('@1'): 3766d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) assert '**' in src 377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) JniParams._remappings.append((src, dest[:-2])) 3786d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) else: 3796d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) assert not '@' in dest 3806d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) JniParams._remappings.append((src, dest)) 381868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ExtractJNINamespace(contents): 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)') 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) m = re.findall(re_jni_namespace, contents) 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not m: 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '' 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return m[0] 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ExtractFullyQualifiedJavaClassName(java_file_name, contents): 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) re_package = re.compile('.*?package (.*?);') 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) matches = re.findall(re_package, contents) 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not matches: 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise SyntaxError('Unable to find "package" line in %s' % java_file_name) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (matches[0].replace('.', '/') + '/' + 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.path.splitext(os.path.basename(java_file_name))[0]) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4000f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)def ExtractNatives(contents, ptr_type): 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns a list of dict containing information about a native method.""" 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents = contents.replace('\n', '') 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) natives = [] 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) re_native = re.compile(r'(@NativeClassQualifiedName' 405cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '\(\"(?P<native_class_name>.*?)\"\)\s+)?' 406cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '(@NativeCall(\(\"(?P<java_class_name>.*?)\"\))\s+)?' 407cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '(?P<qualifiers>\w+\s\w+|\w+|\s+)\s*native ' 408cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '(?P<return_type>\S*) ' 409cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) '(?P<name>native\w+)\((?P<params>.*?)\);') 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for match in re.finditer(re_native, contents): 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) native = NativeMethod( 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static='static' in match.group('qualifiers'), 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_class_name=match.group('java_class_name'), 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) native_class_name=match.group('native_class_name'), 415c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return_type=match.group('return_type'), 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name=match.group('name').replace('native', ''), 4170f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) params=JniParams.Parse(match.group('params')), 4180f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) ptr_type=ptr_type) 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) natives += [native] 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return natives 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetStaticCastForReturnType(return_type): 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) type_map = { 'String' : 'jstring', 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'java/lang/String' : 'jstring', 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'boolean[]': 'jbooleanArray', 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'byte[]': 'jbyteArray', 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'char[]': 'jcharArray', 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'short[]': 'jshortArray', 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'int[]': 'jintArray', 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'long[]': 'jlongArray', 43246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 'float[]': 'jfloatArray', 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'double[]': 'jdoubleArray' } 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ret = type_map.get(return_type, None) 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if ret: 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return ret 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if return_type.endswith('[]'): 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'jobjectArray' 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetEnvCall(is_constructor, is_static, return_type): 4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Maps the types availabe via env->Call__Method.""" 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if is_constructor: 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'NewObject' 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) env_call_map = {'boolean': 'Boolean', 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'byte': 'Byte', 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'char': 'Char', 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'short': 'Short', 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'int': 'Int', 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'long': 'Long', 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'float': 'Float', 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'void': 'Void', 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'double': 'Double', 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'Object': 'Object', 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) call = env_call_map.get(return_type, 'Object') 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if is_static: 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) call = 'Static' + call 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 'Call' + call + 'Method' 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetMangledParam(datatype): 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns a mangled identifier for the datatype.""" 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(datatype) <= 2: 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return datatype.replace('[', 'A') 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = '' 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for i in range(1, len(datatype)): 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) c = datatype[i] 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if c == '[': 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += 'A' 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif c.isupper() or datatype[i - 1] in ['/', 'L']: 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += c.upper() 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def GetMangledMethodName(name, params, return_type): 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns a mangled method name for the given signature. 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) The returned name can be used as a C identifier and will be unique for all 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) valid overloads of the same method. 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name: string. 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params: list of Param. 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_type: string. 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) A mangled name. 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mangled_items = [] 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for datatype in [return_type] + [x.datatype for x in params]: 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mangled_items += [GetMangledParam(JniParams.JavaToJni(datatype))] 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) mangled_name = name + '_'.join(mangled_items) 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) assert re.match(r'[0-9a-zA-Z_]+', mangled_name) 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return mangled_name 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def MangleCalledByNatives(called_by_natives): 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Mangles all the overloads from the call_by_natives list.""" 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_counts = collections.defaultdict( 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) lambda: collections.defaultdict(lambda: 0)) 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for called_by_native in called_by_natives: 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_class_name = called_by_native.java_class_name 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name = called_by_native.name 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_counts[java_class_name][name] += 1 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for called_by_native in called_by_natives: 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_class_name = called_by_native.java_class_name 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_name = called_by_native.name 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_id_var_name = method_name 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if method_counts[java_class_name][method_name] > 1: 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_id_var_name = GetMangledMethodName(method_name, 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) called_by_native.params, 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) called_by_native.return_type) 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) called_by_native.method_id_var_name = method_id_var_name 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return called_by_natives 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Regex to match the JNI return types that should be included in a 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# ScopedJavaLocalRef. 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RE_SCOPED_JNI_RETURN_TYPES = re.compile('jobject|jclass|jstring|.*Array') 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Regex to match a string like "@CalledByNative public void foo(int bar)". 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)RE_CALLED_BY_NATIVE = re.compile( 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '@CalledByNative(?P<Unchecked>(Unchecked)*?)(?:\("(?P<annotation>.*)"\))?' 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '\s+(?P<prefix>[\w ]*?)' 527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) '\s*(?P<return_type>\S+?)' 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '\s+(?P<name>\w+)' 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '\s*\((?P<params>[^\)]*)\)') 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ExtractCalledByNatives(contents): 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Parses all methods annotated with @CalledByNative. 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents: the contents of the java file. 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) A list of dict with information about the annotated methods. 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) TODO(bulach): return a CalledByNative object. 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Raises: 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ParseError: if unable to parse. 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) called_by_natives = [] 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for match in re.finditer(RE_CALLED_BY_NATIVE, contents): 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) called_by_natives += [CalledByNative( 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_class=False, 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unchecked='Unchecked' in match.group('Unchecked'), 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static='static' in match.group('prefix'), 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_class_name=match.group('annotation') or '', 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_type=match.group('return_type'), 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name=match.group('name'), 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params=JniParams.Parse(match.group('params')))] 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Check for any @CalledByNative occurrences that weren't matched. 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unmatched_lines = re.sub(RE_CALLED_BY_NATIVE, '', contents).split('\n') 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for line1, line2 in zip(unmatched_lines, unmatched_lines[1:]): 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if '@CalledByNative' in line1: 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise ParseError('could not parse @CalledByNative method signature', 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) line1, line2) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MangleCalledByNatives(called_by_natives) 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class JNIFromJavaP(object): 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Uses 'javap' to parse a .class file and generate the JNI header file.""" 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) def __init__(self, contents, options): 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.contents = contents 5694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) self.namespace = options.namespace 570a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for line in contents: 571a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) class_name = re.match( 572a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) '.*?(public).*?(class|interface) (?P<class_name>\S+?)( |\Z)', 573a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) line) 574a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if class_name: 575a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) self.fully_qualified_class = class_name.group('class_name') 576a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) break 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.fully_qualified_class = self.fully_qualified_class.replace('.', '/') 57858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) # Java 7's javap includes type parameters in output, like HashSet<T>. Strip 57958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) # away the <...> and use the raw class name that Java 6 would've given us. 58058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) self.fully_qualified_class = self.fully_qualified_class.split('<', 1)[0] 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JniParams.SetFullyQualifiedClass(self.fully_qualified_class) 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.java_class_name = self.fully_qualified_class.split('/')[-1] 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not self.namespace: 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.namespace = 'JNI_' + self.java_class_name 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) re_method = re.compile('(?P<prefix>.*?)(?P<return_type>\S+?) (?P<name>\w+?)' 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '\((?P<params>.*?)\)') 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.called_by_natives = [] 5881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for lineno, content in enumerate(contents[2:], 2): 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match = re.match(re_method, content) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not match: 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.called_by_natives += [CalledByNative( 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_class=True, 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unchecked=False, 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static='static' in match.group('prefix'), 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_class_name='', 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_type=match.group('return_type').replace('.', '/'), 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name=match.group('name'), 5991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) params=JniParams.Parse(match.group('params').replace('.', '/')), 6001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) signature=JniParams.ParseJavaPSignature(contents[lineno + 1]))] 6011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) re_constructor = re.compile('(.*?)public ' + 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.fully_qualified_class.replace('/', '.') + 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '\((?P<params>.*?)\)') 6041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) for lineno, content in enumerate(contents[2:], 2): 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) match = re.match(re_constructor, content) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not match: 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.called_by_natives += [CalledByNative( 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) system_class=True, 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unchecked=False, 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static=False, 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) java_class_name='', 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_type=self.fully_qualified_class, 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name='Constructor', 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params=JniParams.Parse(match.group('params').replace('.', '/')), 6161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) signature=JniParams.ParseJavaPSignature(contents[lineno + 1]), 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_constructor=True)] 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.called_by_natives = MangleCalledByNatives(self.called_by_natives) 619a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 620a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) self.constant_fields = [] 621a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) re_constant_field = re.compile('.*?public static final int (?P<name>.*?);') 622a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) re_constant_field_value = re.compile( 623a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) '.*?Constant(Value| value): int (?P<value>(-*[0-9]+)?)') 624a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for lineno, content in enumerate(contents[2:], 2): 625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) match = re.match(re_constant_field, content) 626a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if not match: 627a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) continue 628a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value = re.match(re_constant_field_value, contents[lineno + 2]) 629a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if not value: 630a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value = re.match(re_constant_field_value, contents[lineno + 3]) 631a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if value: 632a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) self.constant_fields.append( 633a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ConstantField(name=match.group('name'), 634a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) value=value.group('value'))) 635a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.inl_header_file_generator = InlHeaderFileGenerator( 6374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) self.namespace, self.fully_qualified_class, [], 638a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) self.called_by_natives, self.constant_fields, options) 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetContent(self): 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.inl_header_file_generator.GetContent() 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @staticmethod 6444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) def CreateFromClass(class_file, options): 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class_name = os.path.splitext(os.path.basename(class_file))[0] 646a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) p = subprocess.Popen(args=[options.javap, '-c', '-verbose', 647a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) '-s', class_name], 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cwd=os.path.dirname(class_file), 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stdout=subprocess.PIPE, 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stderr=subprocess.PIPE) 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stdout, _ = p.communicate() 6524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) jni_from_javap = JNIFromJavaP(stdout.split('\n'), options) 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return jni_from_javap 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class JNIFromJavaSource(object): 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Uses the given java source file to generate the JNI header file.""" 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 659a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch # Match single line comments, multiline comments, character literals, and 660a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch # double-quoted strings. 661a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch _comment_remover_regex = re.compile( 662a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', 663a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch re.DOTALL | re.MULTILINE) 664a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch 6654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) def __init__(self, contents, fully_qualified_class, options): 666a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch contents = self._RemoveComments(contents) 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JniParams.SetFullyQualifiedClass(fully_qualified_class) 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) JniParams.ExtractImportsAndInnerClasses(contents) 6695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) jni_namespace = ExtractJNINamespace(contents) or options.namespace 6700f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) natives = ExtractNatives(contents, options.ptr_type) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) called_by_natives = ExtractCalledByNatives(contents) 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(natives) == 0 and len(called_by_natives) == 0: 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) raise SyntaxError('Unable to find any JNI methods for %s.' % 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fully_qualified_class) 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) inl_header_file_generator = InlHeaderFileGenerator( 6764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) jni_namespace, fully_qualified_class, natives, called_by_natives, 677a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) [], options) 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.content = inl_header_file_generator.GetContent() 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 680a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch @classmethod 681a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch def _RemoveComments(cls, contents): 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # We need to support both inline and block comments, and we need to handle 683a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch # strings that contain '//' or '/*'. 684a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch # TODO(bulach): This is a bit hacky. It would be cleaner to use a real Java 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # parser. Maybe we could ditch JNIFromJavaSource and just always use 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # JNIFromJavaP; or maybe we could rewrite this script in Java and use APT. 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # http://code.google.com/p/chromium/issues/detail?id=138941 688a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch def replacer(match): 689a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch # Replace matches that are comments with nothing; return literals/strings 690a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch # unchanged. 691a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch s = match.group(0) 692a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch if s.startswith('/'): 693a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return '' 694a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch else: 695a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return s 696a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch return cls._comment_remover_regex.sub(replacer, contents) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetContent(self): 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return self.content 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) @staticmethod 7024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) def CreateFromFile(java_file_name, options): 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents = file(java_file_name).read() 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) fully_qualified_class = ExtractFullyQualifiedJavaClassName(java_file_name, 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) contents) 7064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return JNIFromJavaSource(contents, fully_qualified_class, options) 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class InlHeaderFileGenerator(object): 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Generates an inline header file for JNI integration.""" 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, namespace, fully_qualified_class, natives, 713a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) called_by_natives, constant_fields, options): 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.namespace = namespace 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.fully_qualified_class = fully_qualified_class 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.class_name = self.fully_qualified_class.split('/')[-1] 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.natives = natives 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.called_by_natives = called_by_natives 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.header_guard = fully_qualified_class.replace('/', '_') + '_JNI' 720a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) self.constant_fields = constant_fields 7215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.options = options 7225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.init_native = self.ExtractInitNative(options) 7235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 7245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def ExtractInitNative(self, options): 7255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for native in self.natives: 7265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if options.jni_init_native_name == 'native' + native.name: 7275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) self.natives.remove(native) 7285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return native 7295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return None 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetContent(self): 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns the content of the JNI binding file.""" 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template = Template("""\ 73403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// This file is autogenerated by 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ${SCRIPT_NAME} 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ${FULLY_QUALIFIED_CLASS} 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef ${HEADER_GUARD} 7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ${HEADER_GUARD} 7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <jni.h> 7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)${INCLUDES} 7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 751010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)#include "base/android/jni_int_wrapper.h" 752010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Step 1: forward declarations. 7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$CLASS_PATH_DEFINITIONS 7565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)$METHOD_ID_DEFINITIONS 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$OPEN_NAMESPACE 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$FORWARD_DECLARATIONS 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 762a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)$CONSTANT_FIELDS 763a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Step 2: method stubs. 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$METHOD_STUBS 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Step 3: RegisterNatives. 7685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)$JNI_NATIVE_METHODS 7695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)$REGISTER_NATIVES 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)$CLOSE_NAMESPACE 7715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)$JNI_REGISTER_NATIVES 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // ${HEADER_GUARD} 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""") 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values = { 7755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'SCRIPT_NAME': self.options.script_name, 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'FULLY_QUALIFIED_CLASS': self.fully_qualified_class, 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'CLASS_PATH_DEFINITIONS': self.GetClassPathDefinitionsString(), 7785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'METHOD_ID_DEFINITIONS': self.GetMethodIDDefinitionsString(), 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'FORWARD_DECLARATIONS': self.GetForwardDeclarationsString(), 780a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 'CONSTANT_FIELDS': self.GetConstantFieldsString(), 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'METHOD_STUBS': self.GetMethodStubsString(), 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'OPEN_NAMESPACE': self.GetOpenNamespaceString(), 7835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'JNI_NATIVE_METHODS': self.GetJNINativeMethodsString(), 7845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'REGISTER_NATIVES': self.GetRegisterNativesString(), 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'CLOSE_NAMESPACE': self.GetCloseNamespaceString(), 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'HEADER_GUARD': self.header_guard, 7875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'INCLUDES': self.GetIncludesString(), 7885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'JNI_REGISTER_NATIVES': self.GetJNIRegisterNativesString() 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return WrapOutput(template.substitute(values)) 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetClassPathDefinitionsString(self): 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = [] 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += [self.GetClassPathDefinitions()] 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n'.join(ret) 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetMethodIDDefinitionsString(self): 7985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Returns the definition of method ids for the called by native methods.""" 7995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not self.options.eager_called_by_natives: 8005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return '' 8015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template("""\ 8025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)jmethodID g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = NULL;""") 8035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret = [] 8045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for called_by_native in self.called_by_natives: 8055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) values = { 8065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, 8075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 8085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret += [template.substitute(values)] 8105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return '\n'.join(ret) 8115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetForwardDeclarationsString(self): 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = [] 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for native in self.natives: 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if native.type != 'method': 8165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += [self.GetForwardDeclaration(native)] 8176e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self.options.native_exports and ret: 8186e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return '\nextern "C" {\n' + "\n".join(ret) + '\n}; // extern "C"' 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n'.join(ret) 8205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 821a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) def GetConstantFieldsString(self): 822a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) if not self.constant_fields: 823a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return '' 824a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ret = ['enum Java_%s_constant_fields {' % self.class_name] 825a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) for c in self.constant_fields: 826a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ret += [' %s = %s,' % (c.name, c.value)] 827a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ret += ['};'] 828a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return '\n'.join(ret) 829a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 8305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetMethodStubsString(self): 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Returns the code corresponding to method stubs.""" 8325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = [] 8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for native in self.natives: 8345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if native.type == 'method': 8355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret += [self.GetNativeMethodStubString(native)] 8365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.options.eager_called_by_natives: 8375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret += self.GetEagerCalledByNativeMethodStubs() 8385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 8395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret += self.GetLazyCalledByNativeMethodStubs() 8406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 8416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self.options.native_exports and ret: 8426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return '\nextern "C" {\n' + "\n".join(ret) + '\n}; // extern "C"' 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n'.join(ret) 8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetLazyCalledByNativeMethodStubs(self): 8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return [self.GetLazyCalledByNativeMethodStub(called_by_native) 8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for called_by_native in self.called_by_natives] 8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetEagerCalledByNativeMethodStubs(self): 8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret = [] 8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.called_by_natives: 8525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret += ['namespace {'] 8535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for called_by_native in self.called_by_natives: 8545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret += [self.GetEagerCalledByNativeMethodStub(called_by_native)] 8555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret += ['} // namespace'] 8565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ret 8575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetIncludesString(self): 8595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not self.options.includes: 8605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return '' 8615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) includes = self.options.includes.split(',') 8625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return '\n'.join('#include "%s"' % x for x in includes) 8635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetKMethodsString(self, clazz): 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = [] 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for native in self.natives: 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (native.java_class_name == clazz or 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (not native.java_class_name and clazz == self.class_name)): 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += [self.GetKMethodArrayEntry(native)] 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n'.join(ret) 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def SubstituteNativeMethods(self, template): 8735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Substitutes JAVA_CLASS and KMETHODS in the provided template.""" 8745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret = [] 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_classes = self.GetUniqueClasses(self.natives) 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_classes[self.class_name] = self.fully_qualified_class 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for clazz in all_classes: 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kmethods = self.GetKMethodsString(clazz) 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if kmethods: 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values = {'JAVA_CLASS': clazz, 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'KMETHODS': kmethods} 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += [template.substitute(values)] 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not ret: return '' 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n' + '\n'.join(ret) 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetJNINativeMethodsString(self): 8875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Returns the implementation of the array of native methods.""" 8886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self.options.native_exports: 8896e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return '' 8905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template("""\ 8915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static const JNINativeMethod kMethods${JAVA_CLASS}[] = { 8925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)${KMETHODS} 8935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 8945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)""") 8955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return self.SubstituteNativeMethods(template) 8965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetRegisterCalledByNativesImplString(self): 8985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Returns the code for registering the called by native methods.""" 8995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not self.options.eager_called_by_natives: 9005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return '' 9015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template("""\ 9025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = ${GET_METHOD_ID_IMPL} 9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} == NULL) { 9045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """) 9075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret = [] 9085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for called_by_native in self.called_by_natives: 9095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) values = { 9105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, 9115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 9125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native), 9135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret += [template.substitute(values)] 9155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return '\n'.join(ret) 9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetRegisterNativesString(self): 9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Returns the code for RegisterNatives.""" 9195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template("""\ 9205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)${REGISTER_NATIVES_SIGNATURE} { 9215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)${CLASSES} 9225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)${NATIVES} 9235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)${CALLED_BY_NATIVES} 9245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 9255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)""") 9275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) signature = 'static bool RegisterNativesImpl(JNIEnv* env' 9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.init_native: 9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) signature += ', jclass clazz)' 9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) signature += ')' 9325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) natives = self.GetRegisterNativesImplString() 9345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) called_by_natives = self.GetRegisterCalledByNativesImplString() 9355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) values = {'REGISTER_NATIVES_SIGNATURE': signature, 9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'CLASSES': self.GetFindClasses(), 9375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'NATIVES': natives, 9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'CALLED_BY_NATIVES': called_by_natives, 9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return template.substitute(values) 9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetRegisterNativesImplString(self): 9435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Returns the shared implementation for RegisterNatives.""" 9446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self.options.native_exports: 9456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return '' 9466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template("""\ 9485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const int kMethods${JAVA_CLASS}Size = arraysize(kMethods${JAVA_CLASS}); 9495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 95003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if (env->RegisterNatives(${JAVA_CLASS}_clazz(env), 9515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kMethods${JAVA_CLASS}, 9525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) kMethods${JAVA_CLASS}Size) < 0) { 9535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) jni_generator::HandleRegistrationError( 95403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) env, ${JAVA_CLASS}_clazz(env), __FILE__); 9555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return false; 9565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)""") 9585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return self.SubstituteNativeMethods(template) 9595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetJNIRegisterNativesString(self): 9615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Returns the implementation for the JNI registration of native methods.""" 9625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not self.init_native: 9635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return '' 9645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template("""\ 9665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)extern "C" JNIEXPORT bool JNICALL 9675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)Java_${FULLY_QUALIFIED_CLASS}_${INIT_NATIVE_NAME}(JNIEnv* env, jclass clazz) { 9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ${NAMESPACE}RegisterNativesImpl(env, clazz); 9695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)""") 9716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self.options.native_exports: 9736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) java_name = JniParams.RemapClassName(self.fully_qualified_class) 9746e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) java_name = java_name.replace('_', '_1').replace('/', '_') 9756e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) else: 9766e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) java_name = self.fully_qualified_class.replace('/', '_') 9776e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 9785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) namespace = '' 9795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.namespace: 9805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) namespace = self.namespace + '::' 9816e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) values = {'FULLY_QUALIFIED_CLASS': java_name, 9825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'INIT_NATIVE_NAME': 'native' + self.init_native.name, 9835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'NAMESPACE': namespace, 9845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'REGISTER_NATIVES_IMPL': self.GetRegisterNativesImplString() 9855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return template.substitute(values) 9875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetOpenNamespaceString(self): 9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.namespace: 9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_namespaces = ['namespace %s {' % ns 9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ns in self.namespace.split('::')] 9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n'.join(all_namespaces) 9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '' 9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetCloseNamespaceString(self): 9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.namespace: 9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_namespaces = ['} // namespace %s' % ns 9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for ns in self.namespace.split('::')] 9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) all_namespaces.reverse() 10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n'.join(all_namespaces) + '\n' 10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '' 10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetJNIFirstParam(self, native): 10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = [] 10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if native.type == 'method': 10065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret = ['jobject jcaller'] 10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) elif native.type == 'function': 10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if native.static: 10095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret = ['jclass jcaller'] 10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ret = ['jobject jcaller'] 10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetParamsInDeclaration(self, native): 10155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns the params for the stub declaration. 10165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) native: the native dictionary describing the method. 10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 10215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) A string containing the params. 10225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 10235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ',\n '.join(self.GetJNIFirstParam(native) + 10245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) [JavaDataTypeToC(param.datatype) + ' ' + 10255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) param.name 10265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for param in native.params]) 10275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetCalledByNativeParamsInDeclaration(self, called_by_native): 1029010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return ',\n '.join([ 1030010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) JavaDataTypeToCForCalledByNativeParam(param.datatype) + ' ' + 1031010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) param.name 1032010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) for param in called_by_native.params]) 10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetForwardDeclaration(self, native): 10356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) template_str = """ 10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS}); 10376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)""" 10386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self.options.native_exports: 10396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) template_str += """ 10406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)__attribute__((visibility("default"))) 10416e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)${RETURN} Java_${JAVA_NAME}_native${NAME}(JNIEnv* env, ${PARAMS}) { 10426e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) return ${NAME}(${PARAMS_IN_CALL}); 10436e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)} 10446e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)""" 10456e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) template = Template(template_str) 10466e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) params_in_call = [] 10476e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if not self.options.pure_native_methods: 10486e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) params_in_call = ['env', 'jcaller'] 10496e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) params_in_call = ', '.join(params_in_call + [p.name for p in native.params]) 10506e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 10516e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) java_name = JniParams.RemapClassName(self.fully_qualified_class) 10526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) java_name = java_name.replace('_', '_1').replace('/', '_') 10536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if native.java_class_name: 10546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) java_name += '_00024' + native.java_class_name 10556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 10565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values = {'RETURN': JavaDataTypeToC(native.return_type), 10575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'NAME': native.name, 10586e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 'JAVA_NAME': java_name, 10596e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 'PARAMS': self.GetParamsInDeclaration(native), 10606e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 'PARAMS_IN_CALL': params_in_call} 10615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return template.substitute(values) 10625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetNativeMethodStubString(self, native): 10645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns stubs for native methods.""" 10656e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self.options.native_exports: 10666e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) template_str = """\ 10676e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)__attribute__((visibility("default"))) 10686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)${RETURN} Java_${JAVA_NAME}_native${NAME}(JNIEnv* env, 10696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) ${PARAMS_IN_DECLARATION}) {""" 10706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) else: 10716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) template_str = """\ 10726e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)static ${RETURN} ${NAME}(JNIEnv* env, ${PARAMS_IN_DECLARATION}) {""" 10736e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) template_str += """ 10745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ${P0_TYPE}* native = reinterpret_cast<${P0_TYPE}*>(${PARAM0_NAME}); 10755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_NATIVE_PTR(env, jcaller, native, "${NAME}"${OPTIONAL_ERROR_RETURN}); 10765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return native->${NAME}(${PARAMS_IN_CALL})${POST_CALL}; 10775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 10786e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)""" 10796e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 10806e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) template = Template(template_str) 10815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params = [] 10825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not self.options.pure_native_methods: 10835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params = ['env', 'jcaller'] 10845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params_in_call = ', '.join(params + [p.name for p in native.params[1:]]) 10855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 10865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_type = JavaDataTypeToC(native.return_type) 10875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) optional_error_return = JavaReturnValueToC(native.return_type) 10885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if optional_error_return: 10895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) optional_error_return = ', ' + optional_error_return 10905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) post_call = '' 10915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): 10925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) post_call = '.Release()' 10936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 10946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self.options.native_exports: 10956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) java_name = JniParams.RemapClassName(self.fully_qualified_class) 10966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) java_name = java_name.replace('_', '_1').replace('/', '_') 10976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if native.java_class_name: 10986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) java_name += '_00024' + native.java_class_name 10996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) else: 11006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) java_name = '' 11016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 11025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values = { 11035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'RETURN': return_type, 11045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'OPTIONAL_ERROR_RETURN': optional_error_return, 11056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 'JAVA_NAME': java_name, 11065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'NAME': native.name, 11075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'PARAMS_IN_DECLARATION': self.GetParamsInDeclaration(native), 11085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'PARAM0_NAME': native.params[0].name, 11095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'P0_TYPE': native.p0_type, 11105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'PARAMS_IN_CALL': params_in_call, 11115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'POST_CALL': post_call 11125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return template.substitute(values) 11145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) def GetArgument(self, param): 1116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return ('as_jint(' + param.name + ')' 1117010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) if param.datatype == 'int' else param.name) 1118010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 1119010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) def GetArgumentsInCall(self, params): 1120010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) """Return a string of arguments to call from native into Java""" 1121010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) return [self.GetArgument(p) for p in params] 1122010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) 11235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetCalledByNativeValues(self, called_by_native): 11245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Fills in necessary values for the CalledByNative methods.""" 112503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) java_class = called_by_native.java_class_name or self.class_name 11265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if called_by_native.static or called_by_native.is_constructor: 11275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_param_in_declaration = '' 112803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) first_param_in_call = ('%s_clazz(env)' % java_class) 11295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 11305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_param_in_declaration = ', jobject obj' 11315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_param_in_call = 'obj' 11325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params_in_declaration = self.GetCalledByNativeParamsInDeclaration( 11335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) called_by_native) 11345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if params_in_declaration: 11355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) params_in_declaration = ', ' + params_in_declaration 1136010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) params_in_call = ', '.join(self.GetArgumentsInCall(called_by_native.params)) 11375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if params_in_call: 11385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) params_in_call = ', ' + params_in_call 11395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pre_call = '' 11405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) post_call = '' 11415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if called_by_native.static_cast: 11425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) pre_call = 'static_cast<%s>(' % called_by_native.static_cast 11435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) post_call = ')' 11445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) check_exception = '' 11455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not called_by_native.unchecked: 11465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) check_exception = 'jni_generator::CheckException(env);' 11475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_type = JavaDataTypeToC(called_by_native.return_type) 11485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) optional_error_return = JavaReturnValueToC(called_by_native.return_type) 11495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if optional_error_return: 11505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) optional_error_return = ', ' + optional_error_return 11515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_declaration = '' 11525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_clause = '' 11535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if return_type != 'void': 11545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) pre_call = ' ' + pre_call 11555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_declaration = return_type + ' ret =' 11565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if re.match(RE_SCOPED_JNI_RETURN_TYPES, return_type): 11575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return_type = 'base::android::ScopedJavaLocalRef<' + return_type + '>' 11585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_clause = 'return ' + return_type + '(env, ret);' 11595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 11605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return_clause = 'return ret;' 11615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return { 116203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 'JAVA_CLASS': java_class, 11635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'RETURN_TYPE': return_type, 11645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'OPTIONAL_ERROR_RETURN': optional_error_return, 11655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'RETURN_DECLARATION': return_declaration, 11665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'RETURN_CLAUSE': return_clause, 11675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'FIRST_PARAM_IN_DECLARATION': first_param_in_declaration, 11685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'PARAMS_IN_DECLARATION': params_in_declaration, 11695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'PRE_CALL': pre_call, 11705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'POST_CALL': post_call, 11715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'ENV_CALL': called_by_native.env_call, 11725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'FIRST_PARAM_IN_CALL': first_param_in_call, 11735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'PARAMS_IN_CALL': params_in_call, 11745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 11755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'CHECK_EXCEPTION': check_exception, 11765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'GET_METHOD_ID_IMPL': self.GetMethodIDImpl(called_by_native) 11775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 11785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetEagerCalledByNativeMethodStub(self, called_by_native): 11805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Returns the implementation of the called by native method.""" 11815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template(""" 11825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static ${RETURN_TYPE} ${METHOD_ID_VAR_NAME}(\ 11835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION}) { 11845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ${RETURN_DECLARATION}${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, 11855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}${PARAMS_IN_CALL})${POST_CALL}; 11865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ${RETURN_CLAUSE} 11875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}""") 11885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) values = self.GetCalledByNativeValues(called_by_native) 11895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return template.substitute(values) 11905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) def GetLazyCalledByNativeMethodStub(self, called_by_native): 11925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) """Returns a string.""" 11935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function_signature_template = Template("""\ 11945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static ${RETURN_TYPE} Java_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}(\ 11955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)JNIEnv* env${FIRST_PARAM_IN_DECLARATION}${PARAMS_IN_DECLARATION})""") 11965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function_header_template = Template("""\ 11975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)${FUNCTION_SIGNATURE} {""") 11985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) function_header_with_unused_template = Template("""\ 11995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)${FUNCTION_SIGNATURE} __attribute__ ((unused)); 12005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)${FUNCTION_SIGNATURE} {""") 12015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template(""" 12025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static base::subtle::AtomicWord g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME} = 0; 12035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)${FUNCTION_HEADER} 12045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) /* Must call RegisterNativesImpl() */ 12055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CHECK_CLAZZ(env, ${FIRST_PARAM_IN_CALL}, 120603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ${JAVA_CLASS}_clazz(env)${OPTIONAL_ERROR_RETURN}); 12075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) jmethodID method_id = 12085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ${GET_METHOD_ID_IMPL} 12095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ${RETURN_DECLARATION} 12105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ${PRE_CALL}env->${ENV_CALL}(${FIRST_PARAM_IN_CALL}, 12115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) method_id${PARAMS_IN_CALL})${POST_CALL}; 12125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ${CHECK_EXCEPTION} 12135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ${RETURN_CLAUSE} 12145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}""") 12155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) values = self.GetCalledByNativeValues(called_by_native) 12165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values['FUNCTION_SIGNATURE'] = ( 12175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function_signature_template.substitute(values)) 12185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if called_by_native.system_class: 12195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values['FUNCTION_HEADER'] = ( 12205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) function_header_with_unused_template.substitute(values)) 12215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 12225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values['FUNCTION_HEADER'] = function_header_template.substitute(values) 12235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return template.substitute(values) 12245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetKMethodArrayEntry(self, native): 12265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template = Template("""\ 12275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { "native${NAME}", ${JNI_SIGNATURE}, reinterpret_cast<void*>(${NAME}) },""") 12285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values = {'NAME': native.name, 12295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'JNI_SIGNATURE': JniParams.Signature(native.params, 12305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) native.return_type, 12315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) True)} 12325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return template.substitute(values) 12335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetUniqueClasses(self, origin): 12355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = {self.class_name: self.fully_qualified_class} 12365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for entry in origin: 12375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class_name = self.class_name 12385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jni_class_path = self.fully_qualified_class 12395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if entry.java_class_name: 12405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) class_name = entry.java_class_name 12415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jni_class_path = self.fully_qualified_class + '$' + class_name 12425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret[class_name] = jni_class_path 12435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ret 12445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetClassPathDefinitions(self): 12465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns the ClassPath constants.""" 12475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = [] 12485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template = Template("""\ 12495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char k${JAVA_CLASS}ClassPath[] = "${JNI_CLASS_PATH}";""") 12505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) native_classes = self.GetUniqueClasses(self.natives) 12515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) called_by_native_classes = self.GetUniqueClasses(self.called_by_natives) 12526e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) if self.options.native_exports: 12536e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) all_classes = called_by_native_classes 12546e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) else: 12556e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) all_classes = native_classes 12566e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) all_classes.update(called_by_native_classes) 12576e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 12585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for clazz in all_classes: 12595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values = { 12605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'JAVA_CLASS': clazz, 1261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 'JNI_CLASS_PATH': JniParams.RemapClassName(all_classes[clazz]), 12625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += [template.substitute(values)] 12645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += '' 126503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 126603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) class_getter_methods = [] 126703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if self.options.native_exports: 126803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) template = Template("""\ 126903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)// Leaking this jclass as we cannot use LazyInstance from some threads. 127003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)base::subtle::AtomicWord g_${JAVA_CLASS}_clazz = 0; 127103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define ${JAVA_CLASS}_clazz(env) \ 127203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)base::android::LazyGetClass(env, k${JAVA_CLASS}ClassPath, \ 127303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)&g_${JAVA_CLASS}_clazz)""") 127403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) else: 12755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) template = Template("""\ 12765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Leaking this jclass as we cannot use LazyInstance from some threads. 127703b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)jclass g_${JAVA_CLASS}_clazz = NULL; 127803b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#define ${JAVA_CLASS}_clazz(env) g_${JAVA_CLASS}_clazz""") 127903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 128003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) for clazz in called_by_native_classes: 12815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values = { 12825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'JAVA_CLASS': clazz, 12835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 12845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += [template.substitute(values)] 128503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) 12865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n'.join(ret) 12875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 12885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetFindClasses(self): 12895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns the imlementation of FindClass for all known classes.""" 12905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.init_native: 129103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if self.options.native_exports: 129203b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) template = Template("""\ 129303b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) base::subtle::Release_Store(&g_${JAVA_CLASS}_clazz, 129403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) static_cast<base::subtle::AtomicWord>(env->NewWeakGlobalRef(clazz));""") 129503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) else: 129603b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) template = Template("""\ 12975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) g_${JAVA_CLASS}_clazz = static_cast<jclass>(env->NewWeakGlobalRef(clazz));""") 12985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 129903b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) if self.options.native_exports: 130003b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) return '\n' 13015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template("""\ 13025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) g_${JAVA_CLASS}_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( 1303c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) base::android::GetClass(env, k${JAVA_CLASS}ClassPath).obj()));""") 13045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = [] 13055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for clazz in self.GetUniqueClasses(self.called_by_natives): 13065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values = {'JAVA_CLASS': clazz} 13075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += [template.substitute(values)] 13085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n'.join(ret) 13095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def GetMethodIDImpl(self, called_by_native): 13115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Returns the implementation of GetMethodID.""" 13125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if self.options.eager_called_by_natives: 13135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template("""\ 13145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)env->Get${STATIC_METHOD_PART}MethodID( 131503b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) ${JAVA_CLASS}_clazz(env), 13165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "${JNI_NAME}", ${JNI_SIGNATURE});""") 13175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) else: 13185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) template = Template("""\ 13195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::android::MethodID::LazyGet< 13205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::android::MethodID::TYPE_${STATIC}>( 132103b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles) env, ${JAVA_CLASS}_clazz(env), 13225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "${JNI_NAME}", 13235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ${JNI_SIGNATURE}, 13245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &g_${JAVA_CLASS}_${METHOD_ID_VAR_NAME}); 13255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)""") 13265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jni_name = called_by_native.name 13275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jni_return_type = called_by_native.return_type 13285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if called_by_native.is_constructor: 13295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jni_name = '<init>' 13305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jni_return_type = 'void' 13311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if called_by_native.signature: 13321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) signature = called_by_native.signature 13331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) else: 13341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) signature = JniParams.Signature(called_by_native.params, 13351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) jni_return_type, 13361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) True) 13375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) values = { 13385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'JAVA_CLASS': called_by_native.java_class_name or self.class_name, 13395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'JNI_NAME': jni_name, 13405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'METHOD_ID_VAR_NAME': called_by_native.method_id_var_name, 13415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'STATIC': 'STATIC' if called_by_native.static else 'INSTANCE', 13425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'STATIC_METHOD_PART': 'Static' if called_by_native.static else '', 13431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 'JNI_SIGNATURE': signature, 13445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 13455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return template.substitute(values) 13465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def WrapOutput(output): 13495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret = [] 13505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for line in output.splitlines(): 13515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Do not wrap lines under 80 characters or preprocessor directives. 13525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(line) < 80 or line.lstrip()[:1] == '#': 13535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) stripped = line.rstrip() 13545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if len(ret) == 0 or len(ret[-1]) or len(stripped): 13555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret.append(stripped) 13565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 13575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) first_line_indent = ' ' * (len(line) - len(line.lstrip())) 13585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subsequent_indent = first_line_indent + ' ' * 4 13595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if line.startswith('//'): 13605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subsequent_indent = '//' + subsequent_indent 13615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) wrapper = textwrap.TextWrapper(width=80, 13625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) subsequent_indent=subsequent_indent, 13635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break_long_words=False) 13645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += [wrapped.rstrip() for wrapped in wrapper.wrap(line)] 13655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ret += [''] 13665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return '\n'.join(ret) 13675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def ExtractJarInputFile(jar_file, input_file, out_dir): 13705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """Extracts input file from jar and returns the filename. 13715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) The input file is extracted to the same directory that the generated jni 13735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) headers will be placed in. This is passed as an argument to script. 13745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Args: 13765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jar_file: the jar file containing the input files to extract. 13775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_files: the list of files to extract from the jar file. 13785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_dir: the name of the directories to extract to. 13795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Returns: 13815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) the name of extracted input file. 13825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 13835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) jar_file = zipfile.ZipFile(jar_file) 13845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) out_dir = os.path.join(out_dir, os.path.dirname(input_file)) 13862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) try: 13875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.makedirs(out_dir) 13882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) except OSError as e: 13892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if e.errno != errno.EEXIST: 13902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) raise 13915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extracted_file_name = os.path.join(out_dir, os.path.basename(input_file)) 13925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with open(extracted_file_name, 'w') as outfile: 13935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) outfile.write(jar_file.read(input_file)) 13945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return extracted_file_name 13965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 13984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def GenerateJNIHeader(input_file, output_file, options): 13995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 14005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if os.path.splitext(input_file)[1] == '.class': 14014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) jni_from_javap = JNIFromJavaP.CreateFromClass(input_file, options) 14025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content = jni_from_javap.GetContent() 14035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 14044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) jni_from_java_source = JNIFromJavaSource.CreateFromFile( 14054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) input_file, options) 14065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content = jni_from_java_source.GetContent() 14075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except ParseError, e: 14085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print e 14095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.exit(1) 14105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if output_file: 14115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not os.path.exists(os.path.dirname(os.path.abspath(output_file))): 14125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) os.makedirs(os.path.dirname(os.path.abspath(output_file))) 14134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if options.optimize_generation and os.path.exists(output_file): 14142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) with file(output_file, 'r') as f: 14152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) existing_content = f.read() 14162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if existing_content == content: 14172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return 14185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) with file(output_file, 'w') as f: 14195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) f.write(content) 14205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 14215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print output 14225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 14244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)def GetScriptName(): 14254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) 14264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base_index = 0 14274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for idx, value in enumerate(script_components): 14284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if value == 'base' or value == 'third_party': 14294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base_index = idx 14304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) break 14314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return os.sep.join(script_components[base_index:]) 14324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 14334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 14345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)def main(argv): 14355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) usage = """usage: %prog [OPTIONS] 14365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)This script will parse the given java source code extracting the native 14375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)declarations and print the header file to stdout (or a file). 14385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)See SampleForTests.java for more details. 14395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) """ 14405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) option_parser = optparse.OptionParser(usage=usage) 1441116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch build_utils.AddDepfileOption(option_parser) 1442116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 144346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) option_parser.add_option('-j', '--jar_file', dest='jar_file', 14445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help='Extract the list of input files from' 14455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ' a specified jar file.' 14465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ' Uses javap to extract the methods from a' 14475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ' pre-compiled class. --input should point' 14485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ' to pre-compiled Java .class files.') 14495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) option_parser.add_option('-n', dest='namespace', 14505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help='Uses as a namespace in the generated header ' 14515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'instead of the javap class name, or when there is ' 14525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'no JNINamespace annotation in the java source.') 14535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) option_parser.add_option('--input_file', 14545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help='Single input file name. The output file name ' 14555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 'will be derived from it. Must be used with ' 14565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--output_dir.') 14575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) option_parser.add_option('--output_dir', 14585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) help='The output directory. Must be used with ' 14595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) '--input') 14602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) option_parser.add_option('--optimize_generation', type="int", 14612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default=0, help='Whether we should optimize JNI ' 14622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'generation by not regenerating files if they have ' 14632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 'not changed.') 1464868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) option_parser.add_option('--jarjar', 1465868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) help='Path to optional jarjar rules file.') 14664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) option_parser.add_option('--script_name', default=GetScriptName(), 14674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) help='The name of this script in the generated ' 14684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 'header.') 14695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) option_parser.add_option('--includes', 14705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help='The comma-separated list of header files to ' 14715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'include in the generated header.') 14725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) option_parser.add_option('--pure_native_methods', 14735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action='store_true', dest='pure_native_methods', 14745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help='When true, the native methods will be called ' 14755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'without any JNI-specific arguments.') 14760f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) option_parser.add_option('--ptr_type', default='int', 14770f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) type='choice', choices=['int', 'long'], 14780f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) help='The type used to represent native pointers in ' 14790f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 'Java code. For 32-bit, use int; ' 14800f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) 'for 64-bit, use long.') 14815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) option_parser.add_option('--jni_init_native_name', default='', 14825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help='The name of the JNI registration method that ' 14835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'is used to initialize all native methods. If a ' 14845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'method with this name is not present in the Java ' 14855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'source file, setting this option is a no-op. When ' 14865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'a method with this name is found however, the ' 14875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'naming convention Java_<packageName>_<className> ' 14885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'will limit the initialization to only the ' 14895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'top-level class.') 14905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) option_parser.add_option('--eager_called_by_natives', 14915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) action='store_true', dest='eager_called_by_natives', 14925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help='When true, the called-by-native methods will ' 14935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 'be initialized in a non-atomic way.') 14945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) option_parser.add_option('--cpp', default='cpp', 14955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help='The path to cpp command.') 14965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) option_parser.add_option('--javap', default='javap', 14975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) help='The path to javap command.') 14986e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) option_parser.add_option('--native_exports', action='store_true', 14996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) help='Native method registration through .so ' 15006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) 'exports.') 15015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options, args = option_parser.parse_args(argv) 15025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if options.jar_file: 15035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_file = ExtractJarInputFile(options.jar_file, options.input_file, 15045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) options.output_dir) 15054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) elif options.input_file: 15065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) input_file = options.input_file 15074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) else: 15084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) option_parser.print_help() 15094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) print '\nError: Must specify --jar_file or --input_file.' 15104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return 1 15115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_file = None 15125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if options.output_dir: 15135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) root_name = os.path.splitext(os.path.basename(input_file))[0] 15145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) output_file = os.path.join(options.output_dir, root_name) + '_jni.h' 1515868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if options.jarjar: 1516868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) with open(options.jarjar) as f: 1517868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) JniParams.SetJarJarMappings(f.read()) 15184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) GenerateJNIHeader(input_file, output_file, options) 15195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1520116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if options.depfile: 1521116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch build_utils.WriteDepfile( 1522116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch options.depfile, 1523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch build_utils.GetPythonDependencies()) 1524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch 15255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 15265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__': 15275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sys.exit(main(sys.argv)) 1528