aboutsummaryrefslogtreecommitdiffhomepage
path: root/third_party/ijar
diff options
context:
space:
mode:
authorGravatar Googler <noreply@google.com>2018-05-30 10:22:00 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-05-30 10:23:11 -0700
commit088d8de6584864adaec82712c8ace601404afd0b (patch)
treeb2b50c1da9e10b1be10fd6527c2381e6ec1153c8 /third_party/ijar
parent547b43e3c41355377beaed703837ce19420d0e31 (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.cc25
-rw-r--r--third_party/ijar/test/BUILD26
-rw-r--r--third_party/ijar/test/GenKotlinModule.java41
-rw-r--r--third_party/ijar/test/IjarTests.java11
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")) {