blob: a913b3b5ca9ce2796d48ad3838186200eaaa3b2d [file] [log] [blame]
// +build android
package jni
import (
"fmt"
"runtime"
"veyron/runtimes/google/jni/util"
"veyron2/ipc"
"veyron2/security"
)
// #cgo LDFLAGS: -ljniwrapper
// #include "jni_wrapper.h"
// // CGO doesn't support variadic functions so we have to hard-code these
// // functions to match the invoking code. Ugh!
// static jobject CallLookupMethod(JNIEnv* env, jobject obj, jmethodID id, jstring str) {
// return (*env)->CallObjectMethod(env, obj, id, str);
// }
import "C"
func newDispatcher(env *C.JNIEnv, jDispatcher C.jobject) (*dispatcher, error) {
// We cannot cache Java environments as they are only valid in the current
// thread. We can, however, cache the Java VM and obtain an environment
// from it in whatever thread happens to be running at the time.
var jVM *C.JavaVM
if status := C.GetJavaVM(env, &jVM); status != 0 {
return nil, fmt.Errorf("couldn't get Java VM from the (Java) environment")
}
// Reference Java dispatcher; it will be de-referenced when the go
// dispatcher created below is garbage-collected (through the finalizer
// callback we setup below).
jDispatcher = C.NewGlobalRef(env, jDispatcher)
d := &dispatcher{
jVM: jVM,
jDispatcher: jDispatcher,
}
runtime.SetFinalizer(d, func(d *dispatcher) {
var env *C.JNIEnv
C.AttachCurrentThread(d.jVM, &env, nil)
defer C.DetachCurrentThread(d.jVM)
C.DeleteGlobalRef(env, d.jDispatcher)
})
return d, nil
}
type dispatcher struct {
jVM *C.JavaVM
jDispatcher C.jobject
}
func (d *dispatcher) Lookup(suffix string) (ipc.Invoker, security.Authorizer, error) {
// Get Java environment.
var env *C.JNIEnv
C.AttachCurrentThread(d.jVM, &env, nil)
defer C.DetachCurrentThread(d.jVM)
// Call Java dispatcher's lookup() method.
lid := C.jmethodID(util.JMethodIDPtr(env, C.GetObjectClass(env, d.jDispatcher), "lookup", fmt.Sprintf("(%s)%s", util.StringSign, util.ObjectSign)))
jObj := C.CallLookupMethod(env, d.jDispatcher, lid, C.jstring(util.JStringPtr(env, suffix)))
if err := util.JExceptionMsg(env); err != nil {
return nil, nil, fmt.Errorf("error invoking Java dispatcher's lookup() method: %v", err)
}
if jObj == nil {
// Lookup returned null object, which means that the dispatcher isn't
// handling the object - this is not an error.
return nil, nil, nil
}
i, err := newInvoker(env, d.jVM, jObj)
if err != nil {
return nil, nil, err
}
// TODO(spetrovic): create JNI version of authorizer that invokes Java's
// authorizer methods.
return i, security.NewACLAuthorizer(security.ACL{security.AllPrincipals: security.LabelSet(security.AdminLabel)}), nil
}