diff options
author | torne@chromium.org <torne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-29 13:51:23 +0000 |
---|---|---|
committer | torne@chromium.org <torne@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-05-29 13:51:23 +0000 |
commit | 4f2f30ce91f71f32fd795de099cdcf52d7c43fca (patch) | |
tree | 3bb1e02c3fa5e8091cbad10d141326a500cd2eac /base | |
parent | 077c17db78a7a170543bead8b19cae03b86daeaa (diff) | |
download | chromium_src-4f2f30ce91f71f32fd795de099cdcf52d7c43fca.zip chromium_src-4f2f30ce91f71f32fd795de099cdcf52d7c43fca.tar.gz chromium_src-4f2f30ce91f71f32fd795de099cdcf52d7c43fca.tar.bz2 |
Android: allow JNI generator to be used with jarjar.
When using jarjar to rename Java packages to avoid name conflicts, the
generated JNI code no longer works as it refers to the old name. Support
using the jarjar remapping list during JNI generation to generate code
that refers to the post-remapping names, since the JNI headers are not
intended to be read by humans anyway.
BUG=
Review URL: https://chromiumcodereview.appspot.com/15715006
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@202856 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rwxr-xr-x | base/android/jni_generator/jni_generator.py | 45 | ||||
-rwxr-xr-x | base/android/jni_generator/jni_generator_tests.py | 79 |
2 files changed, 118 insertions, 6 deletions
diff --git a/base/android/jni_generator/jni_generator.py b/base/android/jni_generator/jni_generator.py index f71f553..de865d5 100755 --- a/base/android/jni_generator/jni_generator.py +++ b/base/android/jni_generator/jni_generator.py @@ -119,6 +119,7 @@ class JniParams(object): _fully_qualified_class = '' _package = '' _inner_classes = [] + _remappings = [] @staticmethod def SetFullyQualifiedClass(fully_qualified_class): @@ -173,14 +174,14 @@ class JniParams(object): return prefix + pod_param_map[param] if '/' in param: # Coming from javap, use the fully qualified param directly. - return prefix + 'L' + param + ';' + return prefix + 'L' + JniParams.RemapClassName(param) + ';' for qualified_name in (object_param_list + [JniParams._fully_qualified_class] + JniParams._inner_classes): if (qualified_name.endswith('/' + param) or qualified_name.endswith('$' + param.replace('.', '$')) or qualified_name == 'L' + param): - return prefix + qualified_name + ';' + return prefix + JniParams.RemapClassName(qualified_name) + ';' # Is it from an import? (e.g. referecing Class from import pkg.Class; # note that referencing an inner class Inner from import pkg.Class.Inner @@ -194,7 +195,7 @@ class JniParams(object): 'and used by JNI (%s). Please import the outer ' 'class and use Outer.Inner instead.' % (qualified_name, param)) - return prefix + qualified_name + ';' + return prefix + JniParams.RemapClassName(qualified_name) + ';' # Is it an inner class from an outer class import? (e.g. referencing # Class.Inner from import pkg.Class). @@ -204,10 +205,12 @@ class JniParams(object): inner = components[-1] for qualified_name in JniParams._imports: if qualified_name.endswith('/' + outer): - return prefix + qualified_name + '$' + inner + ';' + return (prefix + JniParams.RemapClassName(qualified_name) + + '$' + inner + ';') # Type not found, falling back to same package as this class. - return prefix + 'L' + JniParams._package + '/' + param + ';' + return (prefix + 'L' + + JniParams.RemapClassName(JniParams._package + '/' + param) + ';') @staticmethod def Signature(params, returns, wrap): @@ -238,6 +241,31 @@ class JniParams(object): ret += [param] return ret + @staticmethod + def RemapClassName(class_name): + """Remaps class names using the jarjar mapping table.""" + for old, new in JniParams._remappings: + if old in class_name: + return class_name.replace(old, new, 1) + return class_name + + @staticmethod + def SetJarJarMappings(mappings): + """Parse jarjar mappings from a string.""" + JniParams._remappings = [] + for line in mappings.splitlines(): + keyword, src, dest = line.split() + if keyword != 'rule': + continue + assert src.endswith('.**') + src = src[:-2].replace('.', '/') + dest = dest.replace('.', '/') + if dest.endswith('@0'): + JniParams._remappings.append((src, dest[:-2] + src)) + else: + assert dest.endswith('@1') + JniParams._remappings.append((src, dest[:-2])) + def ExtractJNINamespace(contents): re_jni_namespace = re.compile('.*?@JNINamespace\("(.*?)"\)') @@ -860,7 +888,7 @@ const char k${JAVA_CLASS}ClassPath[] = "${JNI_CLASS_PATH}";""") for clazz in all_classes: values = { 'JAVA_CLASS': clazz, - 'JNI_CLASS_PATH': all_classes[clazz], + 'JNI_CLASS_PATH': JniParams.RemapClassName(all_classes[clazz]), } ret += [template.substitute(values)] ret += '' @@ -1014,6 +1042,8 @@ See SampleForTests.java for more details. default=0, help='Whether we should optimize JNI ' 'generation by not regenerating files if they have ' 'not changed.') + option_parser.add_option('--jarjar', + help='Path to optional jarjar rules file.') options, args = option_parser.parse_args(argv) if options.jar_file: input_file = ExtractJarInputFile(options.jar_file, options.input_file, @@ -1024,6 +1054,9 @@ See SampleForTests.java for more details. if options.output_dir: root_name = os.path.splitext(os.path.basename(input_file))[0] output_file = os.path.join(options.output_dir, root_name) + '_jni.h' + if options.jarjar: + with open(options.jarjar) as f: + JniParams.SetJarJarMappings(f.read()) GenerateJNIHeader(input_file, output_file, options.namespace, options.optimize_generation) diff --git a/base/android/jni_generator/jni_generator_tests.py b/base/android/jni_generator/jni_generator_tests.py index f6dd3c9..f008f39 100755 --- a/base/android/jni_generator/jni_generator_tests.py +++ b/base/android/jni_generator/jni_generator_tests.py @@ -1937,6 +1937,85 @@ static bool RegisterNativesImpl(JNIEnv* env) { self.assertTrue(len(line) > 80, ('Expected #ifndef line to be > 80 chars: ', line)) + def testJarJarRemapping(self): + test_data = """ + package org.chromium.example.jni_generator; + + import org.chromium.example2.Test; + + class Example { + private static native void nativeTest(Test t); + } + """ + jni_generator.JniParams.SetJarJarMappings( + """rule org.chromium.example.** com.test.@1 + rule org.chromium.example2.** org.test2.@0""") + jni_from_java = jni_generator.JNIFromJavaSource( + test_data, 'org/chromium/example/jni_generator/Example') + jni_generator.JniParams.SetJarJarMappings('') + golden_content = """\ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// This file is autogenerated by +// base/android/jni_generator/jni_generator_tests.py +// For +// org/chromium/example/jni_generator/Example + +#ifndef org_chromium_example_jni_generator_Example_JNI +#define org_chromium_example_jni_generator_Example_JNI + +#include <jni.h> + +#include "base/android/jni_android.h" +#include "base/android/scoped_java_ref.h" +#include "base/basictypes.h" +#include "base/logging.h" + +using base::android::ScopedJavaLocalRef; + +// Step 1: forward declarations. +namespace { +const char kExampleClassPath[] = "com/test/jni_generator/Example"; +// Leaking this jclass as we cannot use LazyInstance from some threads. +jclass g_Example_clazz = NULL; +} // namespace + +static void Test(JNIEnv* env, jclass clazz, + jobject t); + +// Step 2: method stubs. + +// Step 3: RegisterNatives. + +static bool RegisterNativesImpl(JNIEnv* env) { + + g_Example_clazz = reinterpret_cast<jclass>(env->NewGlobalRef( + base::android::GetClass(env, kExampleClassPath).obj())); + static const JNINativeMethod kMethodsExample[] = { + { "nativeTest", +"(" +"Lorg/test2/org/chromium/example2/Test;" +")" +"V", reinterpret_cast<void*>(Test) }, + }; + const int kMethodsExampleSize = arraysize(kMethodsExample); + + if (env->RegisterNatives(g_Example_clazz, + kMethodsExample, + kMethodsExampleSize) < 0) { + LOG(ERROR) << "RegisterNatives failed in " << __FILE__; + return false; + } + + return true; +} + +#endif // org_chromium_example_jni_generator_Example_JNI +""" + self.assertTextEquals(golden_content, jni_from_java.GetContent()) + def testImports(self): import_header = """ // Copyright (c) 2012 The Chromium Authors. All rights reserved. |