Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: libadblockplus-android/jni/JniFileSystem.cpp

Issue 29424615: Issue 4231 - Fix unstable FilterEngineTest.testSetRemoveFilterChangeCallback (Closed)
Patch Set: changed impl for reading file as bytes array, modified test. AndroidFileSystem now does not resolve… Created May 29, 2017, 11:26 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2017 eyeo GmbH
4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation.
8 *
9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include "JniCallbacks.h"
19 #include "AdblockPlus/FileSystem.h"
20 #include "Utils.h"
21 #include <istream>
22 #include <streambuf>
23
24 class RuntimeErrorWithErrno : public std::runtime_error
25 {
26 public:
27 explicit RuntimeErrorWithErrno(const std::string& message)
28 : std::runtime_error(message + " (" + strerror(errno) + ")")
29 {
30 }
31 };
32
33 struct membuf: std::streambuf {
34 membuf(char const* base, size_t size) {
35 char* p(const_cast<char*>(base));
36 this->setg(p, p, p + size);
37 }
38 };
39
40 struct imemstream: virtual membuf, std::istream {
41 imemstream(char const* base, size_t size)
42 : membuf(base, size)
43 , std::istream(static_cast<std::streambuf*>(this)) {
44 }
45 };
sergei 2017/08/07 12:50:00 All these things should be in the anonymous namesp
46
47 // precached in JNI_OnLoad and released in JNI_OnUnload
48 JniGlobalReference<jclass>* statResultClass;
49 jmethodID existsMethod;
50 jmethodID isDirectoryMethod;
51 jmethodID isFileMethod;
52 jmethodID getLastModifiedMethod;
53
54 void JniFileSystem_OnLoad(JavaVM* vm, JNIEnv* env, void* reserved)
55 {
56 statResultClass = new JniGlobalReference<jclass>(env, env->FindClass(PKG("File System$StatResult")));
57 existsMethod = env->GetMethodID(statResultClass->Get(), "exists", "()Z");
58 isDirectoryMethod = env->GetMethodID(statResultClass->Get(), "isDirectory", "( )Z");
59 isFileMethod = env->GetMethodID(statResultClass->Get(), "isFile", "()Z");
60 getLastModifiedMethod = env->GetMethodID(statResultClass->Get(), "getLastModif ied", "()J");
61 }
62
63 void JniFileSystem_OnUnload(JavaVM* vm, JNIEnv* env, void* reserved)
64 {
65 if (statResultClass)
66 {
67 delete statResultClass;
68 statResultClass = NULL;
sergei 2017/08/07 12:50:00 nullptr?
69 }
70 }
71
72 static jlong JNICALL JniCtor(JNIEnv* env, jclass clazz, jobject callbackObject)
sergei 2017/08/07 12:49:59 I think that it should be done a little bit differ
73 {
74 try
75 {
76 return JniPtrToLong(new AdblockPlus::FileSystemPtr(new JniFileSystemCallback (env, callbackObject)));
77 }
78 CATCH_THROW_AND_RETURN(env, 0)
79 }
80
81 static void JNICALL JniDtor(JNIEnv* env, jclass clazz, jlong ptr)
82 {
83 delete JniLongToTypePtr<AdblockPlus::FileSystemPtr>(ptr);
84 }
85
86 JniFileSystemCallback::JniFileSystemCallback(JNIEnv* env, jobject callbackObject )
87 : JniCallbackBase(env, callbackObject)
88 {
89 }
90
91 std::shared_ptr<std::istream> JniFileSystemCallback::Read(const std::string& pat h) const
92 {
93 JNIEnvAcquire env(GetJavaVM());
94
95 jmethodID method = env->GetMethodID(
96 *JniLocalReference<jclass>(*env, env->GetObjectClass(GetCallbackObject())),
97 "read",
98 "(Ljava/lang/String;)[B");
99
100 JniLocalReference<jstring> jPath(*env, env->NewStringUTF(path.c_str()));
101 jbyteArray jData = (jbyteArray)env->CallObjectMethod(GetCallbackObject(), meth od, *jPath);
102 if (CheckAndLogJavaException(*env))
103 throw new RuntimeErrorWithErrno("Failed to open file (File not found)");
104
105 int dataLength = env->GetArrayLength(jData);
106 char* cData = new char[dataLength];
107 env->GetByteArrayRegion(jData, 0, dataLength, reinterpret_cast<jbyte*>(cData)) ;
108
109 std::shared_ptr<std::istream> cSharedStream(new imemstream(cData, dataLength)) ;
110 return cSharedStream;
111 }
112
113 void JniFileSystemCallback::Write(const std::string& path, std::shared_ptr<std:: istream> dataStreamPtr)
114 {
115 JNIEnvAcquire env(GetJavaVM());
116
117 jmethodID method = env->GetMethodID(
118 *JniLocalReference<jclass>(*env, env->GetObjectClass(GetCallbackObject())),
119 "write",
120 "(Ljava/lang/String;[B)V");
121
122 JniLocalReference<jstring> jPath(*env, env->NewStringUTF(path.c_str()));
123
124 // read all the data from the stream into buffer (no appropriate way to pass s treams over JNI)
125 std::istream* dataStream = dataStreamPtr.get();
126 dataStream->seekg(0, std::ios::end);
127 int dataLength = dataStream->tellg();
128 char* cData = new char[dataLength];
129 dataStream->seekg(0, std::ios::beg);
130 dataStream->read(cData, dataLength);
131
132 jbyteArray jData = env->NewByteArray(dataLength);
133 env->SetByteArrayRegion(jData, 0, dataLength, reinterpret_cast<jbyte*>(cData)) ;
134
135 env->CallVoidMethod(GetCallbackObject(), method, *jPath, jData);
136 CheckAndLogJavaException(*env);
137 delete[] cData;
138 }
139
140 void JniFileSystemCallback::Move(const std::string& fromPath, const std::string& toPath)
141 {
142 JNIEnvAcquire env(GetJavaVM());
143
144 jmethodID method = env->GetMethodID(
145 *JniLocalReference<jclass>(*env, env->GetObjectClass(GetCallbackObject())),
146 "move",
147 "(Ljava/lang/String;Ljava/lang/String;)V");
148
149 JniLocalReference<jstring> jFromPath(*env, env->NewStringUTF(fromPath.c_str()) );
150 JniLocalReference<jstring> jToPath(*env, env->NewStringUTF(toPath.c_str()));
151
152 env->CallVoidMethod(GetCallbackObject(), method, *jFromPath, *jToPath);
153 CheckAndLogJavaException(*env);
154 }
155
156 void JniFileSystemCallback::Remove(const std::string& path)
157 {
158 JNIEnvAcquire env(GetJavaVM());
159
160 jmethodID method = env->GetMethodID(
161 *JniLocalReference<jclass>(*env, env->GetObjectClass(GetCallbackObject())),
162 "remove",
163 "(Ljava/lang/String;)V");
164
165 JniLocalReference<jstring> jPath(*env, env->NewStringUTF(path.c_str()));
166
167 env->CallVoidMethod(GetCallbackObject(), method, *jPath);
168 CheckAndLogJavaException(*env);
169 }
170
171 AdblockPlus::FileSystem::StatResult JniFileSystemCallback::Stat(const std::strin g& path) const
172 {
173 JNIEnvAcquire env(GetJavaVM());
174
175 jmethodID method = env->GetMethodID(
176 *JniLocalReference<jclass>(*env, env->GetObjectClass(GetCallbackObject())),
177 "stat",
178 "(Ljava/lang/String;)" TYP("FileSystem$StatResult"));
179
180 JniLocalReference<jstring> jPath(*env, env->NewStringUTF(path.c_str()));
181
182 jobject jStatResult = env->CallObjectMethod(GetCallbackObject(), method, *jPat h);
183 CheckAndLogJavaException(*env);
184
185 AdblockPlus::FileSystem::StatResult statResult;
186
187 statResult.exists = env->CallBooleanMethod(jStatResult, existsMethod) ? JNI_TR UE : JNI_FALSE;
188 CheckAndLogJavaException(*env);
189
190 statResult.isDirectory = env->CallBooleanMethod(jStatResult, isDirectoryMethod ) ? JNI_TRUE : JNI_FALSE;
191 CheckAndLogJavaException(*env);
192
193 statResult.isFile = env->CallBooleanMethod(jStatResult, isFileMethod) ? JNI_TR UE : JNI_FALSE;
194 CheckAndLogJavaException(*env);
195
196 statResult.lastModified = env->CallLongMethod(jStatResult, getLastModifiedMeth od);
197 CheckAndLogJavaException(*env);
198
199 return statResult;
200 }
201
202 std::string JniFileSystemCallback::Resolve(const std::string& path) const
203 {
204 JNIEnvAcquire env(GetJavaVM());
205
206 jmethodID method = env->GetMethodID(
207 *JniLocalReference<jclass>(*env, env->GetObjectClass(GetCallbackObject())),
208 "resolve",
209 "(Ljava/lang/String;)Ljava/lang/String;");
210
211 JniLocalReference<jstring> jPath(*env, env->NewStringUTF(path.c_str()));
212
213 jstring jRet = (jstring)env->CallObjectMethod(GetCallbackObject(), method, *jP ath);
214 CheckAndLogJavaException(*env);
215
216 return JniJavaToStdString(*env, jRet);
217 }
218
219 static JNINativeMethod methods[] =
220 {
221 { (char*)"ctor", (char*)"(Ljava/lang/Object;)J", (void*)JniCtor },
222 { (char*)"dtor", (char*)"(J)V", (void*)JniDtor }
223 };
224
225 extern "C" JNIEXPORT void JNICALL Java_org_adblockplus_libadblockplus_FileSystem _registerNatives(JNIEnv *env, jclass clazz)
226 {
227 env->RegisterNatives(clazz, methods, sizeof(methods) / sizeof(methods[0]));
228 }
OLDNEW

Powered by Google App Engine
This is Rietveld