blob: 8b63eecfb59d0b2fad11899b5da02e8fb8e0f7b4 [file] [log] [blame]
// +build android
package jni
import (
"fmt"
"runtime"
"veyron/runtimes/google/jni/util"
inaming "veyron/runtimes/google/naming"
"veyron2/naming"
"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 jstring CallContextStringMethod(JNIEnv* env, jobject obj, jmethodID id) {
// return (jstring)(*env)->CallObjectMethod(env, obj, id);
// }
// static jint CallContextIntMethod(JNIEnv* env, jobject obj, jmethodID id) {
// return (*env)->CallIntMethod(env, obj, id);
// }
// static jobject CallContextPublicIDMethod(JNIEnv* env, jobject obj, jmethodID id) {
// return (*env)->CallObjectMethod(env, obj, id);
// }
// static jobject CallContextLabelMethod(JNIEnv* env, jobject obj, jmethodID id) {
// return (*env)->CallObjectMethod(env, obj, id);
// }
import "C"
func newContext(env *C.JNIEnv, jContext C.jobject) *context {
// 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 {
panic("couldn't get Java VM from the (Java) environment")
}
// Reference Java context; it will be de-referenced when the go context
// created below is garbage-collected (through the finalizer callback we
// setup just below).
jContext = C.NewGlobalRef(env, jContext)
c := &context{
jVM: jVM,
jContext: jContext,
}
runtime.SetFinalizer(c, func(c *context) {
var env *C.JNIEnv
C.AttachCurrentThread(c.jVM, &env, nil)
defer C.DetachCurrentThread(c.jVM)
C.DeleteGlobalRef(env, c.jContext)
})
return c
}
type context struct {
jVM *C.JavaVM
jContext C.jobject
}
func (c *context) Method() string {
var env *C.JNIEnv
C.AttachCurrentThread(c.jVM, &env, nil)
defer C.DetachCurrentThread(c.jVM)
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jContext), "method", fmt.Sprintf("()%s", util.StringSign)))
return util.GoString(env, C.CallContextStringMethod(env, c.jContext, mid))
}
func (c *context) Name() string {
var env *C.JNIEnv
C.AttachCurrentThread(c.jVM, &env, nil)
defer C.DetachCurrentThread(c.jVM)
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jContext), "name", fmt.Sprintf("()%s", util.StringSign)))
return util.GoString(env, C.CallContextStringMethod(env, c.jContext, mid))
}
func (c *context) Suffix() string {
var env *C.JNIEnv
C.AttachCurrentThread(c.jVM, &env, nil)
defer C.DetachCurrentThread(c.jVM)
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jContext), "suffix", fmt.Sprintf("()%s", util.StringSign)))
return util.GoString(env, C.CallContextStringMethod(env, c.jContext, mid))
}
func (c *context) Label() security.Label {
var env *C.JNIEnv
C.AttachCurrentThread(c.jVM, &env, nil)
defer C.DetachCurrentThread(c.jVM)
labelSign := "Lcom/veyron2/security/Label;"
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jContext), "label", fmt.Sprintf("()%s", labelSign)))
jLabel := C.CallContextLabelMethod(env, c.jContext, mid)
return security.Label(util.JIntField(env, jLabel, "value"))
}
func (c *context) CaveatDischarges() security.CaveatDischargeMap {
// TODO(spetrovic): implement this method.
return nil
}
func (c *context) LocalID() security.PublicID {
var env *C.JNIEnv
C.AttachCurrentThread(c.jVM, &env, nil)
defer C.DetachCurrentThread(c.jVM)
publicIDSign := "Lcom/veyron2/security/PublicID;"
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jContext), "localID", fmt.Sprintf("()%s", publicIDSign)))
jID := C.CallContextPublicIDMethod(env, c.jContext, mid)
return newPublicID(env, jID)
}
func (c *context) RemoteID() security.PublicID {
var env *C.JNIEnv
C.AttachCurrentThread(c.jVM, &env, nil)
defer C.DetachCurrentThread(c.jVM)
publicIDSign := "Lcom/veyron2/security/PublicID;"
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jContext), "remoteID", fmt.Sprintf("()%s", publicIDSign)))
jID := C.CallContextPublicIDMethod(env, c.jContext, mid)
return newPublicID(env, jID)
}
func (c *context) LocalEndpoint() naming.Endpoint {
var env *C.JNIEnv
C.AttachCurrentThread(c.jVM, &env, nil)
defer C.DetachCurrentThread(c.jVM)
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jContext), "localEndpoint", fmt.Sprintf("()%s", util.StringSign)))
// TODO(spetrovic): create a Java Endpoint interface.
epStr := util.GoString(env, C.CallContextStringMethod(env, c.jContext, mid))
ep, err := inaming.NewEndpoint(epStr)
if err != nil {
panic("Couldn't parse endpoint string: " + epStr)
}
return ep
}
func (c *context) RemoteEndpoint() naming.Endpoint {
var env *C.JNIEnv
C.AttachCurrentThread(c.jVM, &env, nil)
defer C.DetachCurrentThread(c.jVM)
mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jContext), "remoteEndpoint", fmt.Sprintf("()%s", util.StringSign)))
// TODO(spetrovic): create a Java Endpoint interface.
epStr := util.GoString(env, C.CallContextStringMethod(env, c.jContext, mid))
ep, err := inaming.NewEndpoint(epStr)
if err != nil {
panic("Couldn't parse endpoint string: " + epStr)
}
return ep
}