blob: 13a4db387eba03addc1f7951f5a4f3e8142b9c56 [file] [log] [blame]
Narayan Kamath0c1869e2013-11-29 17:59:15 +00001/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18#define LOG_TAG "StrictJarFile"
19
Ian Rogersb3aacde2014-11-04 15:21:13 -080020#include <memory>
Narayan Kamath0c1869e2013-11-29 17:59:15 +000021#include <string>
22
23#include "JNIHelp.h"
24#include "JniConstants.h"
25#include "ScopedLocalRef.h"
26#include "ScopedUtfChars.h"
Narayan Kamath0c1869e2013-11-29 17:59:15 +000027#include "jni.h"
28#include "ziparchive/zip_archive.h"
29#include "cutils/log.h"
30
Narayan Kamath59059202015-01-08 13:41:33 +000031// The method ID for ZipEntry.<init>(String,String,JJJIII[BJJ)
32static jmethodID zipEntryCtor;
33
Narayan Kamath0c1869e2013-11-29 17:59:15 +000034static void throwIoException(JNIEnv* env, const int32_t errorCode) {
35 jniThrowException(env, "java/io/IOException", ErrorCodeString(errorCode));
36}
37
Piotr Jastrzebski8c585e92014-08-07 12:42:26 +010038static jobject newZipEntry(JNIEnv* env, const ZipEntry& entry, jstring entryName) {
Narayan Kamath59059202015-01-08 13:41:33 +000039 return env->NewObject(JniConstants::zipEntryClass,
Narayan Kamath0c1869e2013-11-29 17:59:15 +000040 zipEntryCtor,
41 entryName,
42 NULL, // comment
43 static_cast<jlong>(entry.crc32),
44 static_cast<jlong>(entry.compressed_length),
45 static_cast<jlong>(entry.uncompressed_length),
46 static_cast<jint>(entry.method),
47 static_cast<jint>(0), // time
48 static_cast<jint>(0), // modData
49 NULL, // byte[] extra
Narayan Kamath0c1869e2013-11-29 17:59:15 +000050 static_cast<jlong>(-1), // local header offset
51 static_cast<jlong>(entry.offset));
52}
53
54static jlong StrictJarFile_nativeOpenJarFile(JNIEnv* env, jobject, jstring fileName) {
55 ScopedUtfChars fileChars(env, fileName);
56 if (fileChars.c_str() == NULL) {
57 return static_cast<jlong>(-1);
58 }
59
60 ZipArchiveHandle handle;
61 int32_t error = OpenArchive(fileChars.c_str(), &handle);
62 if (error) {
63 throwIoException(env, error);
64 return static_cast<jlong>(-1);
65 }
66
67 return reinterpret_cast<jlong>(handle);
68}
69
70class IterationHandle {
71 public:
Piotr Jastrzebski63395c62014-08-08 16:12:14 +010072 IterationHandle() :
73 cookie_(NULL) {
Narayan Kamath0c1869e2013-11-29 17:59:15 +000074 }
75
76 void** CookieAddress() {
77 return &cookie_;
78 }
79
Narayan Kamath0c1869e2013-11-29 17:59:15 +000080 ~IterationHandle() {
Piotr Jastrzebskie1319c52014-08-08 13:04:08 +010081 EndIteration(cookie_);
Narayan Kamath0c1869e2013-11-29 17:59:15 +000082 }
83
84 private:
85 void* cookie_;
Narayan Kamath0c1869e2013-11-29 17:59:15 +000086};
87
88
89static jlong StrictJarFile_nativeStartIteration(JNIEnv* env, jobject, jlong nativeHandle,
90 jstring prefix) {
91 ScopedUtfChars prefixChars(env, prefix);
92 if (prefixChars.c_str() == NULL) {
93 return static_cast<jlong>(-1);
94 }
95
Piotr Jastrzebski63395c62014-08-08 16:12:14 +010096 IterationHandle* handle = new IterationHandle();
Narayan Kamath0c1869e2013-11-29 17:59:15 +000097 int32_t error = 0;
98 if (prefixChars.size() == 0) {
99 error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
Yusuke Sato29e82852015-06-25 14:44:09 -0700100 handle->CookieAddress(), NULL, NULL);
Narayan Kamath0c1869e2013-11-29 17:59:15 +0000101 } else {
Yusuke Sato29e82852015-06-25 14:44:09 -0700102 ZipString entry_name(prefixChars.c_str());
Narayan Kamath0c1869e2013-11-29 17:59:15 +0000103 error = StartIteration(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
Yusuke Sato29e82852015-06-25 14:44:09 -0700104 handle->CookieAddress(), &entry_name, NULL);
Narayan Kamath0c1869e2013-11-29 17:59:15 +0000105 }
106
107 if (error) {
108 throwIoException(env, error);
109 return static_cast<jlong>(-1);
110 }
111
112 return reinterpret_cast<jlong>(handle);
113}
114
115static jobject StrictJarFile_nativeNextEntry(JNIEnv* env, jobject, jlong iterationHandle) {
116 ZipEntry data;
Yusuke Sato29e82852015-06-25 14:44:09 -0700117 ZipString entryName;
Narayan Kamath0c1869e2013-11-29 17:59:15 +0000118
119 IterationHandle* handle = reinterpret_cast<IterationHandle*>(iterationHandle);
120 const int32_t error = Next(*handle->CookieAddress(), &data, &entryName);
121 if (error) {
122 delete handle;
123 return NULL;
124 }
125
Ian Rogersb3aacde2014-11-04 15:21:13 -0800126 std::unique_ptr<char[]> entryNameCString(new char[entryName.name_length + 1]);
Narayan Kamath0c1869e2013-11-29 17:59:15 +0000127 memcpy(entryNameCString.get(), entryName.name, entryName.name_length);
128 entryNameCString[entryName.name_length] = '\0';
129 ScopedLocalRef<jstring> entryNameString(env, env->NewStringUTF(entryNameCString.get()));
130
Piotr Jastrzebski8c585e92014-08-07 12:42:26 +0100131 return newZipEntry(env, data, entryNameString.get());
Narayan Kamath0c1869e2013-11-29 17:59:15 +0000132}
133
134static jobject StrictJarFile_nativeFindEntry(JNIEnv* env, jobject, jlong nativeHandle,
135 jstring entryName) {
136 ScopedUtfChars entryNameChars(env, entryName);
137 if (entryNameChars.c_str() == NULL) {
138 return NULL;
139 }
140
141 ZipEntry data;
142 const int32_t error = FindEntry(reinterpret_cast<ZipArchiveHandle>(nativeHandle),
Yusuke Sato29e82852015-06-25 14:44:09 -0700143 ZipString(entryNameChars.c_str()), &data);
Narayan Kamath0c1869e2013-11-29 17:59:15 +0000144 if (error) {
145 return NULL;
146 }
147
Piotr Jastrzebski8c585e92014-08-07 12:42:26 +0100148 return newZipEntry(env, data, entryName);
Narayan Kamath0c1869e2013-11-29 17:59:15 +0000149}
150
151static void StrictJarFile_nativeClose(JNIEnv*, jobject, jlong nativeHandle) {
152 CloseArchive(reinterpret_cast<ZipArchiveHandle>(nativeHandle));
153}
154
155static JNINativeMethod gMethods[] = {
156 NATIVE_METHOD(StrictJarFile, nativeOpenJarFile, "(Ljava/lang/String;)J"),
157 NATIVE_METHOD(StrictJarFile, nativeStartIteration, "(JLjava/lang/String;)J"),
158 NATIVE_METHOD(StrictJarFile, nativeNextEntry, "(J)Ljava/util/zip/ZipEntry;"),
159 NATIVE_METHOD(StrictJarFile, nativeFindEntry, "(JLjava/lang/String;)Ljava/util/zip/ZipEntry;"),
160 NATIVE_METHOD(StrictJarFile, nativeClose, "(J)V"),
161};
162
163void register_java_util_jar_StrictJarFile(JNIEnv* env) {
164 jniRegisterNativeMethods(env, "java/util/jar/StrictJarFile", gMethods, NELEM(gMethods));
165
Narayan Kamath59059202015-01-08 13:41:33 +0000166 zipEntryCtor = env->GetMethodID(JniConstants::zipEntryClass, "<init>",
167 "(Ljava/lang/String;Ljava/lang/String;JJJIII[BJJ)V");
168 LOG_ALWAYS_FATAL_IF(zipEntryCtor == NULL, "Unable to find ZipEntry.<init>");
Narayan Kamath0c1869e2013-11-29 17:59:15 +0000169}