blob: a48ca07664f7178df97c3a9557f6908507442333 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you 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.
#include <jni.h>
#include <glog/logging.h>
#include <google/protobuf/io/zero_copy_stream_impl.h>
#include <string>
#include <map>
#include <mesos/mesos.hpp>
#include <mesos/v1/mesos.hpp>
#include <mesos/v1/scheduler/scheduler.hpp>
#include "construct.hpp"
using namespace mesos;
using std::map;
using std::string;
template <typename T>
T parse(const void* data, int size)
{
// This should always get called with data that can be parsed (i.e.,
// ParseFromZeroCopyStream should never return false) because we
// have static type checking in Java and C++. A dynamic language
// will not have this luxury.
google::protobuf::io::ArrayInputStream stream(data, size);
T t;
bool parsed = t.ParseFromZeroCopyStream(&stream);
CHECK(parsed) << "Unexpected failure while parsing protobuf";
return t;
}
template <class TMessage>
TMessage constructViaProtobufSerialization(JNIEnv* env, jobject jobj)
{
jclass clazz = env->GetObjectClass(jobj);
// byte[] data = obj.toByteArray();
jmethodID toByteArray = env->GetMethodID(clazz, "toByteArray", "()[B");
jbyteArray jdata = (jbyteArray) env->CallObjectMethod(jobj, toByteArray);
jbyte* data = env->GetByteArrayElements(jdata, nullptr);
jsize length = env->GetArrayLength(jdata);
TMessage result = parse<TMessage>(data, length);
env->ReleaseByteArrayElements(jdata, data, 0);
return result;
}
bool construct(JNIEnv* env, jboolean jbool)
{
return jbool == JNI_TRUE;
}
template <>
string construct(JNIEnv* env, jobject jobj)
{
jstring js = (jstring) jobj;
const char* s = env->GetStringUTFChars(js, nullptr);
CHECK(s != nullptr) << "Out of memory!";
string result(s);
env->ReleaseStringUTFChars(js, s);
return result;
}
template <>
map<string, string> construct(JNIEnv *env, jobject jobj)
{
map<string, string> result;
jclass clazz = env->GetObjectClass(jobj);
// Set entrySet = map.entrySet();
jmethodID entrySet = env->GetMethodID(clazz, "entrySet", "()Ljava/util/Set;");
jobject jentrySet = env->CallObjectMethod(jobj, entrySet);
clazz = env->GetObjectClass(jentrySet);
// Iterator iterator = entrySet.iterator();
jmethodID iterator =
env->GetMethodID(clazz, "iterator", "()Ljava/util/Iterator;");
jobject jiterator = env->CallObjectMethod(jentrySet, iterator);
clazz = env->GetObjectClass(jiterator);
// while (iterator.hasNext()) {
jmethodID hasNext = env->GetMethodID(clazz, "hasNext", "()Z");
jmethodID next = env->GetMethodID(clazz, "next", "()Ljava/lang/Object;");
while (env->CallBooleanMethod(jiterator, hasNext)) {
// Map.Entry entry = iterator.next();
jobject jentry = env->CallObjectMethod(jiterator, next);
clazz = env->GetObjectClass(jentry);
// String key = entry.getKey();
jmethodID getKey =
env->GetMethodID(clazz, "getKey", "()Ljava/lang/Object;");
jobject jkey = env->CallObjectMethod(jentry, getKey);
// String value = entry.getValue();
jmethodID getValue =
env->GetMethodID(clazz, "getValue", "()Ljava/lang/Object;");
jobject jvalue = env->CallObjectMethod(jentry, getValue);
const string& key = construct<string>(env, jkey);
const string& value = construct<string>(env, jvalue);
result[key] = value;
}
return result;
}
template <>
FrameworkInfo construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<FrameworkInfo>(env, jobj);
}
template <>
Credential construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<Credential>(env, jobj);
}
template <>
Filters construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<Filters>(env, jobj);
}
template <>
FrameworkID construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<FrameworkID>(env, jobj);
}
template <>
ExecutorID construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<ExecutorID>(env, jobj);
}
template <>
TaskID construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<TaskID>(env, jobj);
}
template <>
SlaveID construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<SlaveID>(env, jobj);
}
template <>
OfferID construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<OfferID>(env, jobj);
}
template <>
TaskState construct(JNIEnv* env, jobject jobj)
{
// int value = obj.getNumber(value);
jclass clazz = env->FindClass("org/apache/mesos/Protos$TaskState");
jmethodID getNumber = env->GetStaticMethodID(clazz, "getNumber", "()I");
jint jvalue = env->CallIntMethod(jobj, getNumber);
return (TaskState) jvalue;
}
template <>
TaskInfo construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<TaskInfo>(env, jobj);
}
template <>
TaskStatus construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<TaskStatus>(env, jobj);
}
template <>
ExecutorInfo construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<ExecutorInfo>(env, jobj);
}
template <>
Request construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<Request>(env, jobj);
}
template <>
Offer::Operation construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<Offer::Operation>(env, jobj);
}
template <>
v1::Credential construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<v1::Credential>(env, jobj);
}
template <>
v1::FrameworkInfo construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<v1::FrameworkInfo>(env, jobj);
}
template<>
v1::scheduler::Call construct(JNIEnv* env, jobject jobj)
{
return constructViaProtobufSerialization<v1::scheduler::Call>(env, jobj);
}