diff options
author | Googler <noreply@google.com> | 2018-05-30 10:22:00 -0700 |
---|---|---|
committer | Copybara-Service <copybara-piper@google.com> | 2018-05-30 10:23:11 -0700 |
commit | 088d8de6584864adaec82712c8ace601404afd0b (patch) | |
tree | b2b50c1da9e10b1be10fd6527c2381e6ec1153c8 /third_party/ijar | |
parent | 547b43e3c41355377beaed703837ce19420d0e31 (diff) |
Prevent ijar from stripping out .kotlin_module files, which are needed for extension functions.
PiperOrigin-RevId: 198579700
Diffstat (limited to 'third_party/ijar')
-rw-r--r-- | third_party/ijar/ijar.cc | 25 | ||||
-rw-r--r-- | third_party/ijar/test/BUILD | 26 | ||||
-rw-r--r-- | third_party/ijar/test/GenKotlinModule.java | 41 | ||||
-rw-r--r-- | third_party/ijar/test/IjarTests.java | 11 |
4 files changed, 101 insertions, 2 deletions
diff --git a/third_party/ijar/ijar.cc b/third_party/ijar/ijar.cc index a50b97037d..3776782a16 100644 --- a/third_party/ijar/ijar.cc +++ b/third_party/ijar/ijar.cc @@ -35,6 +35,8 @@ bool StripClass(u1 *&classdata_out, const u1 *classdata_in, size_t in_length); const char *CLASS_EXTENSION = ".class"; const size_t CLASS_EXTENSION_LENGTH = strlen(CLASS_EXTENSION); +const char *KOTLIN_MODULE_EXTENSION = ".kotlin_module"; +const size_t KOTLIN_MODULE_EXTENSION_LENGTH = strlen(KOTLIN_MODULE_EXTENSION); const char *MANIFEST_DIR_PATH = "META-INF/"; const size_t MANIFEST_DIR_PATH_LENGTH = strlen(MANIFEST_DIR_PATH); @@ -81,8 +83,29 @@ class JarStripperProcessor : public JarExtractorProcessor { const char *injecting_rule_kind); }; +static bool StartsWith(const char *str, const size_t str_len, + const char *prefix, const size_t prefix_len) { + return str_len >= prefix_len && strncmp(str, prefix, prefix_len) == 0; +} + +static bool EndsWith(const char *str, const size_t str_len, const char *suffix, + const size_t suffix_len) { + return str_len >= suffix_len && + strcmp(str + str_len - suffix_len, suffix) == 0; +} + +static bool IsKotlinModule(const char *filename, const size_t filename_len) { + return StartsWith(filename, filename_len, MANIFEST_DIR_PATH, + MANIFEST_DIR_PATH_LENGTH) && + EndsWith(filename, filename_len, KOTLIN_MODULE_EXTENSION, + KOTLIN_MODULE_EXTENSION_LENGTH); +} + bool JarStripperProcessor::Accept(const char *filename, const u4 /*attr*/) { const size_t filename_len = strlen(filename); + if (IsKotlinModule(filename, filename_len)) { + return true; + } if (filename_len < CLASS_EXTENSION_LENGTH || strcmp(filename + filename_len - CLASS_EXTENSION_LENGTH, CLASS_EXTENSION) != 0) { @@ -106,7 +129,7 @@ void JarStripperProcessor::Process(const char *filename, const u4 /*attr*/, if (verbose) { fprintf(stderr, "INFO: StripClass: %s\n", filename); } - if (IsModuleInfo(filename)) { + if (IsModuleInfo(filename) || IsKotlinModule(filename, strlen(filename))) { u1 *q = builder_->NewFile(filename, 0); memcpy(q, data, size); builder_->FinishFile(size, /* compress: */ false, /* compute_crc: */ true); diff --git a/third_party/ijar/test/BUILD b/third_party/ijar/test/BUILD index 816ae1221d..d2ad67ef10 100644 --- a/third_party/ijar/test/BUILD +++ b/third_party/ijar/test/BUILD @@ -223,6 +223,31 @@ genrule( tools = ["//third_party/ijar"], ) +java_binary( + name = "GenKotlinModule", + testonly = 1, + srcs = ["GenKotlinModule.java"], + main_class = "GenKotlinModule", + deps = ["//third_party:guava"], +) + +genrule( + name = "kotlin_module", + testonly = 1, + outs = ["kotlin_module.jar"], + cmd = "$(location :GenKotlinModule) $@", + tools = [":GenKotlinModule"], +) + +genrule( + name = "kotlin_module_interface", + testonly = 1, + srcs = [":kotlin_module.jar"], + outs = ["kotlin_module-interface.jar"], + cmd = "$(location //third_party/ijar) $< $@", + tools = ["//third_party/ijar"], +) + java_test( name = "IjarTests", size = "small", @@ -247,6 +272,7 @@ java_test( ":jar_with_manifest_nostrip", ":jar_without_manifest_nostrip", ":jar_without_manifest_nostrip_idempotence", + ":kotlin_module-interface.jar", ":liblocal_and_anonymous_lib.jar", ":local_and_anonymous-interface.jar", ":module_info-interface.jar", diff --git a/third_party/ijar/test/GenKotlinModule.java b/third_party/ijar/test/GenKotlinModule.java new file mode 100644 index 0000000000..b681d34d00 --- /dev/null +++ b/third_party/ijar/test/GenKotlinModule.java @@ -0,0 +1,41 @@ +// Copyright 2017 The Bazel Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import static java.nio.charset.StandardCharsets.UTF_8; + +import com.google.common.io.ByteStreams; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.jar.JarOutputStream; +import java.util.zip.ZipEntry; + +/** A generator for a jar file containing a .kotlin-module file, and one real class file. */ +public class GenKotlinModule { + public static void main(String[] args) throws IOException { + try (JarOutputStream jos = new JarOutputStream(Files.newOutputStream(Paths.get(args[0])))) { + addEntry(jos, "META-INF/bar.kotlin_module"); + jos.write("hello".getBytes(UTF_8)); + + addEntry(jos, "java/lang/String.class"); + ByteStreams.copy(String.class.getResourceAsStream("/java/lang/String.class"), jos); + } + } + + private static void addEntry(JarOutputStream jos, String name) throws IOException { + ZipEntry ze = new ZipEntry(name); + ze.setTime(0); + jos.putNextEntry(ze); + } +} diff --git a/third_party/ijar/test/IjarTests.java b/third_party/ijar/test/IjarTests.java index f8e487ff64..6be993290f 100644 --- a/third_party/ijar/test/IjarTests.java +++ b/third_party/ijar/test/IjarTests.java @@ -250,7 +250,7 @@ public class IjarTests { Enumeration<JarEntry> entries = jf.entries(); while (entries.hasMoreElements()) { JarEntry je = entries.nextElement(); - if (!je.getName().endsWith(".class")) { + if (!je.getName().endsWith(".class") && !je.getName().endsWith(".kotlin_module")) { continue; } classes.put(je.getName(), ByteStreams.toByteArray(jf.getInputStream(je))); @@ -285,6 +285,15 @@ public class IjarTests { } @Test + public void kotlinModule() throws Exception { + Map<String, byte[]> lib = readJar("third_party/ijar/test/kotlin_module-interface.jar"); + assertThat(lib.keySet()) + .containsExactly("java/lang/String.class", "META-INF/bar.kotlin_module"); + // ijar passes kotlin modules through unmodified + assertThat(new String(lib.get("META-INF/bar.kotlin_module"), UTF_8)).isEqualTo("hello"); + } + + @Test public void testTargetLabel() throws Exception { try (JarFile jf = new JarFile("third_party/ijar/test/interface_ijar_testlib_with_target_label.jar")) { |