Index: jni/AndroidWebRequest.cpp |
=================================================================== |
--- a/jni/AndroidWebRequest.cpp |
+++ b/jni/AndroidWebRequest.cpp |
@@ -20,19 +20,63 @@ |
#include "Utils.h" |
#include "debug.h" |
-struct JavaException : public std::exception |
+namespace |
{ |
- jthrowable ex; |
- |
- JavaException(jthrowable e) : ex(e) |
+ std::string ExtractExceptionMessage(JNIEnv* env, jthrowable throwable) |
{ |
+ jclass throwableClass = env->FindClass("java/lang/Throwable"); |
+ jmethodID throwableToStringMethodId = env->GetMethodID(throwableClass, "toString", "()Ljava/lang/String;"); |
+ jstring javaMessage = static_cast<jstring>(env->CallObjectMethod(throwable, throwableToStringMethodId)); |
+ const char* nativeMessage = env->GetStringUTFChars(javaMessage, 0); |
+ const std::string message = nativeMessage; |
+ env->ReleaseStringUTFChars(javaMessage, nativeMessage); |
+ return message; |
} |
- const char* what() const throw() |
+ class JavaException : public std::exception |
{ |
- return "Java Exception"; |
+ public: |
+ JavaException(JNIEnv* env) |
+ : env(env), throwable(env->ExceptionOccurred()) |
+ { |
+ env->ExceptionClear(); |
+ message = ExtractExceptionMessage(env, throwable); |
+ } |
+ |
+ virtual ~JavaException() throw() |
+ { |
+ } |
+ |
+ const char* what() const throw() |
+ { |
+ return ("Java Exception: " + message).c_str(); |
Wladimir Palant
2013/11/22 17:51:03
You are creating a temporary std::string instance
Felix Dahlke
2013/11/22 18:01:12
Done.
|
+ } |
+ |
+ bool IsInstanceOf(const std::string& className) const |
+ { |
+ jclass clazz = env->FindClass(className.c_str()); |
+ if (!clazz) |
+ return false; |
+ bool isInstance = env->IsInstanceOf(throwable, clazz); |
+ env->DeleteLocalRef(clazz); |
+ return isInstance; |
+ } |
+ |
+ private: |
+ JNIEnv* env; |
+ jthrowable throwable; |
+ std::string message; |
+ }; |
+ |
+ int64_t ExceptionToStatus(const JavaException& exception) |
+ { |
+ if (exception.IsInstanceOf("java/net/MalformedURLException")) |
+ return AdblockPlus::WebRequest::NS_ERROR_MALFORMED_URI; |
+ if (exception.IsInstanceOf("java/net/SocketTimeoutException")) |
+ return AdblockPlus::WebRequest::NS_ERROR_NET_TIMEOUT; |
+ return AdblockPlus::WebRequest::NS_ERROR_FAILURE; |
} |
-}; |
+} |
AndroidWebRequest::AndroidWebRequest(JavaVM*& gJvm) : globalJvm(gJvm) |
{ |
@@ -104,9 +148,6 @@ |
} |
AdblockPlus::ServerResponse result; |
- result.status = NS_ERROR_FAILURE; |
- result.responseStatus = 0; |
- |
try |
{ |
// URL jUrl = new URL(url) |
@@ -114,19 +155,19 @@ |
jobject jUrl = jniEnv->NewObject(jUrlClass, jUrlConstructorID, jUrlStr); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
jniEnv->DeleteLocalRef(jUrlStr); |
// HttpURLConnection connection = (HttpURLConnection) jUrl.openConnection(); |
jobject jConnection = jniEnv->CallObjectMethod(jUrl, jUrlOpenConnectionID); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
// connection.setRequestMethod("GET"); |
jstring jMethod = jniEnv->NewStringUTF("GET"); |
jniEnv->CallVoidMethod(jConnection, jConnectionSetMethodID, jMethod); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
jniEnv->DeleteLocalRef(jMethod); |
for (int i = 0; i < requestHeaders.size(); i++) |
@@ -136,7 +177,7 @@ |
jstring jValue = jniEnv->NewStringUTF(requestHeaders[i].second.c_str()); |
jniEnv->CallVoidMethod(jConnection, jConnectionSetRequestPropertyID, jHeader, jValue); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
jniEnv->DeleteLocalRef(jHeader); |
jniEnv->DeleteLocalRef(jValue); |
} |
@@ -144,26 +185,26 @@ |
// connection.connect(); |
jniEnv->CallVoidMethod(jConnection, jConnectionConnectID); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
// int lenghtOfFile = connection.getContentLength(); |
jint lenghtOfFile = jniEnv->CallIntMethod(jConnection, jConnectionGetContentLengthID); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
D(D_WARN, "Size: %d", lenghtOfFile); |
// result.responseStatus = connection.getResponseCode(); |
result.responseStatus = jniEnv->CallIntMethod(jConnection, jConnectionGetResponseCodeID); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
/* Read response data */ |
// String jEncoding = connection.getContentEncoding(); |
jstring jEncoding = (jstring) jniEnv->CallObjectMethod(jConnection, jConnectionGetContentEncodingID); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
if (jEncoding == NULL) |
jEncoding = jniEnv->NewStringUTF("utf-8"); |
@@ -171,19 +212,19 @@ |
// InputStream jis = connection.getInputStream(); |
jobject jis = jniEnv->CallObjectMethod(jConnection, jConnectionGetInputStreamID); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
// InputStreamReader jisr = new InputStreamReader(jis, jEncoding); |
jobject jisr = jniEnv->NewObject(jInputStreamReaderClass, jInputStreamReaderConstructorID, jis, jEncoding); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
jniEnv->DeleteLocalRef(jEncoding); |
// BufferedReader jin = new BufferedReader(jisr); |
jobject jin = jniEnv->NewObject(jBufferedReaderClass, jBufferedReaderConstructorID, jisr); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
// char[] jBuffer = new char[0x10000]; |
jcharArray jBuffer = jniEnv->NewCharArray(0x10000); |
@@ -191,7 +232,7 @@ |
// StringBuilder jout = new StringBuilder(); |
jobject jout = jniEnv->NewObject(jStringBuilderClass, jStringBuilderConstructorID); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
jlong total = 0; |
jint read; |
@@ -203,14 +244,14 @@ |
// read = jin.read(buffer, 0, buffer.length); |
read = jniEnv->CallIntMethod(jin, jBufferedReaderReadID, jBuffer, 0, jBufferLength); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
if (read > 0) |
{ |
// jout.append(buffer, 0, read); |
jniEnv->CallObjectMethod(jout, jStringBuilderAppendID, jBuffer, 0, jBufferLength); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
total += read; |
} |
@@ -220,14 +261,14 @@ |
// String jData = out.toString(); |
jstring jData = (jstring) jniEnv->CallObjectMethod(jout, jStringBuilderToStringID); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
result.responseText = GetString(jniEnv, jData); |
// jin.close(); |
jniEnv->CallVoidMethod(jin, jBufferedReaderCloseID); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
jint i = 0; |
while (true) |
@@ -235,12 +276,12 @@ |
// String jHeaderName = connection.getHeaderFieldKey(i) |
jstring jHeaderName = (jstring) jniEnv->CallObjectMethod(jConnection, jConnectionGetHeaderFieldKeyID, i); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
// String jHeaderValue = connection.getHeaderField(i) |
jstring jHeaderValue = (jstring) jniEnv->CallObjectMethod(jConnection, jConnectionGetHeaderFieldID, i); |
if (jniEnv->ExceptionCheck()) |
- throw JavaException(jniEnv->ExceptionOccurred()); |
+ throw JavaException(jniEnv); |
if (!jHeaderValue) |
break; |
@@ -259,19 +300,13 @@ |
} |
D(D_WARN, "Finished downloading"); |
- result.status = AdblockPlus::DefaultWebRequest::NS_OK; |
+ result.status = NS_OK; |
} |
catch(JavaException& e) |
{ |
- jniEnv->ExceptionClear(); |
- jclass jThrowableClass = jniEnv->FindClass("java/lang/Throwable"); |
- jmethodID jThrowableToStringID = jniEnv->GetMethodID(jThrowableClass, "toString", "()Ljava/lang/String;"); |
- jstring jMsg = (jstring) jniEnv->CallObjectMethod(e.ex, jThrowableToStringID); |
- const char* msg = jniEnv->GetStringUTFChars(jMsg, 0); |
- D(D_ERROR, "Java Exception: %s", msg); |
- jniEnv->ReleaseStringUTFChars(jMsg, msg); |
- jniEnv->DeleteLocalRef(jMsg); |
- result.status = AdblockPlus::DefaultWebRequest::NS_ERROR_FAILURE; |
+ result.responseStatus = 0; |
+ result.status = ExceptionToStatus(e); |
+ D(D_ERROR, "%s", e.what()); |
} |
catch (const std::exception& e) |
{ |