forked from organicmaps/organicmaps
[platform] JNI layer for http uploader class
This commit is contained in:
parent
68d332b783
commit
2f11131c9f
8 changed files with 160 additions and 50 deletions
|
@ -20,13 +20,13 @@ jclass g_bookmarkClazz;
|
|||
jclass g_myTrackerClazz;
|
||||
jclass g_httpClientClazz;
|
||||
jclass g_httpParamsClazz;
|
||||
jclass g_httpHeaderClazz;
|
||||
jclass g_platformSocketClazz;
|
||||
jclass g_utilsClazz;
|
||||
jclass g_bannerClazz;
|
||||
jclass g_ratingClazz;
|
||||
jclass g_arrayListClazz;
|
||||
jclass g_loggerFactoryClazz;
|
||||
jclass g_keyValueClazz;
|
||||
jclass g_httpUploaderClazz;
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
@ -44,12 +44,13 @@ JNI_OnLoad(JavaVM * jvm, void *)
|
|||
g_myTrackerClazz = jni::GetGlobalClassRef(env, "com/my/tracker/MyTracker");
|
||||
g_httpClientClazz = jni::GetGlobalClassRef(env, "com/mapswithme/util/HttpClient");
|
||||
g_httpParamsClazz = jni::GetGlobalClassRef(env, "com/mapswithme/util/HttpClient$Params");
|
||||
g_httpHeaderClazz = jni::GetGlobalClassRef(env, "com/mapswithme/util/HttpClient$HttpHeader");
|
||||
g_platformSocketClazz = jni::GetGlobalClassRef(env, "com/mapswithme/maps/location/PlatformSocket");
|
||||
g_utilsClazz = jni::GetGlobalClassRef(env, "com/mapswithme/util/Utils");
|
||||
g_bannerClazz = jni::GetGlobalClassRef(env, "com/mapswithme/maps/ads/Banner");
|
||||
g_ratingClazz = jni::GetGlobalClassRef(env, "com/mapswithme/maps/ugc/UGC$Rating");
|
||||
g_loggerFactoryClazz = jni::GetGlobalClassRef(env, "com/mapswithme/util/log/LoggerFactory");
|
||||
g_keyValueClazz = jni::GetGlobalClassRef(env, "com/mapswithme/util/KeyValue");
|
||||
g_httpUploaderClazz = jni::GetGlobalClassRef(env, "com/mapswithme/util/HttpUploader");
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
@ -65,12 +66,13 @@ JNI_OnUnload(JavaVM *, void *)
|
|||
env->DeleteGlobalRef(g_myTrackerClazz);
|
||||
env->DeleteGlobalRef(g_httpClientClazz);
|
||||
env->DeleteGlobalRef(g_httpParamsClazz);
|
||||
env->DeleteGlobalRef(g_httpHeaderClazz);
|
||||
env->DeleteGlobalRef(g_platformSocketClazz);
|
||||
env->DeleteGlobalRef(g_utilsClazz);
|
||||
env->DeleteGlobalRef(g_bannerClazz);
|
||||
env->DeleteGlobalRef(g_ratingClazz);
|
||||
env->DeleteGlobalRef(g_loggerFactoryClazz);
|
||||
env->DeleteGlobalRef(g_keyValueClazz);
|
||||
env->DeleteGlobalRef(g_httpUploaderClazz);
|
||||
}
|
||||
} // extern "C"
|
||||
|
||||
|
@ -286,4 +288,30 @@ void DumpDalvikReferenceTables()
|
|||
env->CallStaticVoidMethod(vm_class, dump_mid);
|
||||
env->DeleteLocalRef(vm_class);
|
||||
}
|
||||
|
||||
jobject ToKeyValue(JNIEnv * env, std::pair<std::string, std::string> src)
|
||||
{
|
||||
static jmethodID const PairInit = jni::GetConstructorID(
|
||||
env, g_keyValueClazz, "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
|
||||
jni::TScopedLocalRef key(env, jni::ToJavaString(env, src.first));
|
||||
jni::TScopedLocalRef value(env, jni::ToJavaString(env, src.second));
|
||||
|
||||
return env->NewObject(g_keyValueClazz, PairInit, key.get(), value.get());
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> ToNativeKeyValue(JNIEnv * env, jobject pairOfStrings)
|
||||
{
|
||||
static jfieldID const keyId = env->GetFieldID(g_keyValueClazz, "key",
|
||||
"Ljava/lang/String;");
|
||||
static jfieldID const valueId = env->GetFieldID(g_keyValueClazz, "value",
|
||||
"Ljava/lang/String;");
|
||||
|
||||
jni::ScopedLocalRef<jstring> const key(
|
||||
env, static_cast<jstring>(env->GetObjectField(pairOfStrings, keyId)));
|
||||
jni::ScopedLocalRef<jstring> const value(
|
||||
env, static_cast<jstring>(env->GetObjectField(pairOfStrings, valueId)));
|
||||
|
||||
return { jni::ToNativeString(env, key.get()), jni::ToNativeString(env, value.get()) };
|
||||
}
|
||||
} // namespace jni
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
extern jclass g_mapObjectClazz;
|
||||
extern jclass g_featureIdClazz;
|
||||
|
@ -17,12 +18,13 @@ extern jclass g_bookmarkClazz;
|
|||
extern jclass g_myTrackerClazz;
|
||||
extern jclass g_httpClientClazz;
|
||||
extern jclass g_httpParamsClazz;
|
||||
extern jclass g_httpHeaderClazz;
|
||||
extern jclass g_platformSocketClazz;
|
||||
extern jclass g_utilsClazz;
|
||||
extern jclass g_bannerClazz;
|
||||
extern jclass g_ratingClazz;
|
||||
extern jclass g_loggerFactoryClazz;
|
||||
extern jclass g_keyValueClazz;
|
||||
extern jclass g_httpUploaderClazz;
|
||||
|
||||
namespace jni
|
||||
{
|
||||
|
@ -90,4 +92,28 @@ jobjectArray ToJavaArray(JNIEnv * env, jclass clazz, TContainer const & src, TTo
|
|||
jobjectArray ToJavaStringArray(JNIEnv * env, std::vector<std::string> const & src);
|
||||
|
||||
void DumpDalvikReferenceTables();
|
||||
|
||||
jobject ToKeyValue(JNIEnv * env, std::pair<std::string, std::string> src);
|
||||
|
||||
template <typename Container>
|
||||
jobjectArray ToKeyValueArray(JNIEnv * env, Container const & src)
|
||||
{
|
||||
return jni::ToJavaArray(env, g_keyValueClazz, src,
|
||||
std::bind(&ToKeyValue, std::placeholders::_1, std::placeholders::_2));
|
||||
}
|
||||
|
||||
std::pair<std::string, std::string> ToNativeKeyValue(JNIEnv * env, jobject pairOfStrings);
|
||||
|
||||
template <typename OutputIt>
|
||||
void ToNativekeyValueContainer(JNIEnv * env, jobjectArray src, OutputIt it)
|
||||
{
|
||||
int const length = env->GetArrayLength(src);
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
{
|
||||
jni::ScopedLocalRef<jobject> const arrayItem(env, env->GetObjectArrayElement(src, i));
|
||||
|
||||
*it = ToNativeKeyValue(env, arrayItem.get());
|
||||
++it;
|
||||
}
|
||||
}
|
||||
} // namespace jni
|
||||
|
|
|
@ -1,12 +1,44 @@
|
|||
#include <jni.h>
|
||||
|
||||
#include "com/mapswithme/core/jni_helper.hpp"
|
||||
#include "com/mapswithme/core/ScopedEnv.hpp"
|
||||
#include "com/mapswithme/core/ScopedLocalRef.hpp"
|
||||
|
||||
#include "platform/http_uploader.hpp"
|
||||
|
||||
#include "base/assert.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
|
||||
namespace platform
|
||||
{
|
||||
void HttpUploader::Upload() const
|
||||
{
|
||||
// Dummy implementation.
|
||||
CHECK(m_callback, ());
|
||||
auto env = jni::GetEnv();
|
||||
|
||||
CHECK(env, ());
|
||||
|
||||
static jmethodID const httpUploaderConstructor =
|
||||
jni::GetConstructorID(env, g_httpUploaderClazz, "(Ljava/lang/String;Ljava/lang/String;"
|
||||
"[Lcom/mapswithme/util/KeyValue;"
|
||||
"[Lcom/mapswithme/util/KeyValue;"
|
||||
"Ljava/lang/String;Ljava/lang/String;)V");
|
||||
|
||||
jni::ScopedLocalRef<jstring> const method(env, jni::ToJavaString(env, m_method));
|
||||
jni::ScopedLocalRef<jstring> const url(env, jni::ToJavaString(env, m_url));
|
||||
jni::ScopedLocalRef<jobjectArray> const params(env, jni::ToKeyValueArray(env, m_params));
|
||||
jni::ScopedLocalRef<jobjectArray> const headers(env, jni::ToKeyValueArray(env, m_headers));
|
||||
jni::ScopedLocalRef<jstring> const fileKey(env, jni::ToJavaString(env, m_fileKey));
|
||||
jni::ScopedLocalRef<jstring> const filePath(env, jni::ToJavaString(env, m_filePath));
|
||||
|
||||
jni::ScopedLocalRef<jobject> const httpUploaderObject(
|
||||
env, env->NewObject(g_httpUploaderClazz, httpUploaderConstructor, method.get(), url.get(),
|
||||
params.get(), headers.get(), fileKey.get(), filePath.get()));
|
||||
|
||||
static jmethodID const uploadId = jni::GetMethodID(env, httpUploaderObject, "upload", "()I");
|
||||
|
||||
m_callback(env->CallIntMethod(httpUploaderObject, uploadId), "dummy");
|
||||
}
|
||||
} // namespace platform
|
||||
|
|
|
@ -34,6 +34,7 @@ SOFTWARE.
|
|||
#include "base/logging.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <iterator>
|
||||
#include <unordered_map>
|
||||
|
||||
DECLARE_EXCEPTION(JniException, RootException);
|
||||
|
@ -103,22 +104,12 @@ void SetHeaders(ScopedEnv & env, jobject const params,
|
|||
if (headers.empty())
|
||||
return;
|
||||
|
||||
static jmethodID const headerInit = jni::GetConstructorID(
|
||||
env.get(), g_httpHeaderClazz, "(Ljava/lang/String;Ljava/lang/String;)V");
|
||||
static jmethodID const setHeaders = env->GetMethodID(
|
||||
g_httpParamsClazz, "setHeaders", "([Lcom/mapswithme/util/HttpClient$HttpHeader;)V");
|
||||
g_httpParamsClazz, "setHeaders", "([Lcom/mapswithme/util/KeyValue;)V");
|
||||
|
||||
RethrowOnJniException(env);
|
||||
|
||||
using HeaderPair = std::unordered_map<std::string, std::string>::value_type;
|
||||
auto headerFunc = [](JNIEnv * env, HeaderPair const & item)
|
||||
{
|
||||
jni::TScopedLocalRef first(env, jni::ToJavaString(env, item.first));
|
||||
jni::TScopedLocalRef second(env, jni::ToJavaString(env, item.second));
|
||||
return env->NewObject(g_httpHeaderClazz, headerInit, first.get(), second.get());
|
||||
};
|
||||
jni::TScopedLocalObjectArrayRef jHeaders(env.get(), jni::ToJavaArray(env.get(), g_httpHeaderClazz,
|
||||
headers, headerFunc));
|
||||
jni::TScopedLocalObjectArrayRef jHeaders(env.get(), jni::ToKeyValueArray(env.get(), headers));
|
||||
env->CallVoidMethod(params, setHeaders, jHeaders.get());
|
||||
RethrowOnJniException(env);
|
||||
}
|
||||
|
@ -127,8 +118,6 @@ void LoadHeaders(ScopedEnv & env, jobject const params, std::unordered_map<std::
|
|||
{
|
||||
static jmethodID const getHeaders =
|
||||
env->GetMethodID(g_httpParamsClazz, "getHeaders", "()[Ljava/lang/Object;");
|
||||
static jfieldID const keyId = env->GetFieldID(g_httpHeaderClazz, "key", "Ljava/lang/String;");
|
||||
static jfieldID const valueId = env->GetFieldID(g_httpHeaderClazz, "value", "Ljava/lang/String;");
|
||||
|
||||
jni::ScopedLocalRef<jobjectArray> const headersArray(
|
||||
env.get(), static_cast<jobjectArray>(env->CallObjectMethod(params, getHeaders)));
|
||||
|
@ -136,20 +125,8 @@ void LoadHeaders(ScopedEnv & env, jobject const params, std::unordered_map<std::
|
|||
RethrowOnJniException(env);
|
||||
|
||||
headers.clear();
|
||||
int const length = env->GetArrayLength(headersArray.get());
|
||||
for (size_t i = 0; i < length; ++i)
|
||||
{
|
||||
jni::ScopedLocalRef<jobject> const headerEntry(
|
||||
env.get(), env->GetObjectArrayElement(headersArray.get(), i));
|
||||
jni::ToNativekeyValueContainer(env.get(), headersArray, std::inserter(headers, headers.end()));
|
||||
|
||||
jni::ScopedLocalRef<jstring> const key(
|
||||
env.get(), static_cast<jstring>(env->GetObjectField(headerEntry.get(), keyId)));
|
||||
jni::ScopedLocalRef<jstring> const value(
|
||||
env.get(), static_cast<jstring>(env->GetObjectField(headerEntry.get(), valueId)));
|
||||
|
||||
headers.emplace(jni::ToNativeString(env.get(), key.get()),
|
||||
jni::ToNativeString(env.get(), value.get()));
|
||||
}
|
||||
RethrowOnJniException(env);
|
||||
}
|
||||
|
||||
|
|
|
@ -97,7 +97,7 @@ public final class HttpClient
|
|||
if (!TextUtils.isEmpty(p.cookies))
|
||||
connection.setRequestProperty("Cookie", p.cookies);
|
||||
|
||||
for (HttpHeader header : p.headers)
|
||||
for (KeyValue header : p.headers)
|
||||
{
|
||||
connection.setRequestProperty(header.key, header.value);
|
||||
}
|
||||
|
@ -163,14 +163,14 @@ public final class HttpClient
|
|||
if (header.getKey() == null || header.getValue() == null)
|
||||
continue;
|
||||
|
||||
p.headers.add(new HttpHeader(header.getKey().toLowerCase(), TextUtils.join(", ", header.getValue())));
|
||||
p.headers.add(new KeyValue(header.getKey().toLowerCase(), TextUtils.join(", ", header.getValue())));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
List<String> cookies = connection.getHeaderFields().get("Set-Cookie");
|
||||
if (cookies != null)
|
||||
p.headers.add(new HttpHeader("Set-Cookie", TextUtils.join(", ", cookies)));
|
||||
p.headers.add(new KeyValue("Set-Cookie", TextUtils.join(", ", cookies)));
|
||||
}
|
||||
|
||||
OutputStream ostream;
|
||||
|
@ -244,21 +244,9 @@ public final class HttpClient
|
|||
return url.replaceAll("(token|password|key)=([^&]+)", "***");
|
||||
}
|
||||
|
||||
private static class HttpHeader
|
||||
{
|
||||
HttpHeader(@NonNull String key, @NonNull String value)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String key;
|
||||
public String value;
|
||||
}
|
||||
|
||||
private static class Params
|
||||
{
|
||||
public void setHeaders(@NonNull HttpHeader[] array)
|
||||
public void setHeaders(@NonNull KeyValue[] array)
|
||||
{
|
||||
headers = new ArrayList<>(Arrays.asList(array));
|
||||
}
|
||||
|
@ -282,7 +270,7 @@ public final class HttpClient
|
|||
// Received data is stored here if not null or in data otherwise.
|
||||
String outputFilePath;
|
||||
String cookies;
|
||||
ArrayList<HttpHeader> headers = new ArrayList<>();
|
||||
ArrayList<KeyValue> headers = new ArrayList<>();
|
||||
int httpResponseCode = -1;
|
||||
boolean followRedirects = true;
|
||||
boolean loadHeaders;
|
||||
|
|
41
android/src/com/mapswithme/util/HttpUploader.java
Normal file
41
android/src/com/mapswithme/util/HttpUploader.java
Normal file
|
@ -0,0 +1,41 @@
|
|||
package com.mapswithme.util;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
final class HttpUploader
|
||||
{
|
||||
@NonNull
|
||||
private final String mMethod;
|
||||
@NonNull
|
||||
private final String mUrl;
|
||||
@NonNull
|
||||
private final ArrayList<KeyValue> mParams;
|
||||
@NonNull
|
||||
private final ArrayList<KeyValue> mHeaders;
|
||||
@NonNull
|
||||
private final String mFileKey;
|
||||
@NonNull
|
||||
private final String mFilePath;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private HttpUploader(@NonNull String method, @NonNull String url, @NonNull KeyValue[] params,
|
||||
@NonNull KeyValue[] headers, @NonNull String fileKey, @NonNull String filePath)
|
||||
{
|
||||
mMethod = method;
|
||||
mUrl = url;
|
||||
mParams = new ArrayList<>(Arrays.asList(params));
|
||||
mHeaders = new ArrayList<>(Arrays.asList(headers));
|
||||
mFileKey = fileKey;
|
||||
mFilePath = filePath;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private int upload()
|
||||
{
|
||||
// Dummy. Error code 200 - Http OK.
|
||||
return 200;
|
||||
}
|
||||
}
|
17
android/src/com/mapswithme/util/KeyValue.java
Normal file
17
android/src/com/mapswithme/util/KeyValue.java
Normal file
|
@ -0,0 +1,17 @@
|
|||
package com.mapswithme.util;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
|
||||
final class KeyValue
|
||||
{
|
||||
KeyValue(@NonNull String key, @NonNull String value)
|
||||
{
|
||||
this.key = key;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public final String key;
|
||||
@NonNull
|
||||
public final String value;
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
|
Loading…
Add table
Reference in a new issue