blob: 2d8bd11ce6da486e1e70edce4b0eab1d1c50c13d [file] [log] [blame]
// +build android
package security
import (
"runtime"
"veyron/jni/runtimes/google/util"
inaming "veyron/runtimes/google/naming"
"veyron2/naming"
"veyron2/security"
)
// #cgo LDFLAGS: -ljniwrapper
// #include "jni_wrapper.h"
import "C"
// newJavaContext constructs a new context in java based on the passed go context.
func newJavaContext(env interface{}, context security.Context) C.jobject {
util.GoRef(&context) // Un-refed when the Java Context object is finalized.
return C.jobject(util.NewObjectOrCatch(env, jContextImplClass, []util.Sign{util.LongSign}, &context))
}
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) {
envPtr, freeFunc := util.GetEnv(c.jVM)
env := (*C.JNIEnv)(envPtr)
defer freeFunc()
C.DeleteGlobalRef(env, c.jContext)
})
return c
}
// context is the go interface to the java implementation of security.Context
type context struct {
jVM *C.JavaVM
jContext C.jobject
}
func (c *context) Method() string {
return c.callStringMethod("method")
}
func (c *context) Name() string {
return c.callStringMethod("name")
}
func (c *context) Suffix() string {
return c.callStringMethod("suffix")
}
func (c *context) Label() security.Label {
envPtr, freeFunc := util.GetEnv(c.jVM)
env := (*C.JNIEnv)(envPtr)
defer freeFunc()
labelSign := util.ClassSign("com.veyron2.security.Label")
jLabel := C.jobject(util.CallObjectMethodOrCatch(env, c.jContext, "label", nil, labelSign))
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 {
envPtr, freeFunc := util.GetEnv(c.jVM)
env := (*C.JNIEnv)(envPtr)
defer freeFunc()
publicIDSign := util.ClassSign("com.veyron2.security.PublicID")
jID := C.jobject(util.CallObjectMethodOrCatch(env, c.jContext, "localID", nil, publicIDSign))
idPtr := util.CallLongMethodOrCatch(env, jID, "getNativePtr", nil)
return (*(*security.PublicID)(util.Ptr(idPtr)))
}
func (c *context) RemoteID() security.PublicID {
envPtr, freeFunc := util.GetEnv(c.jVM)
env := (*C.JNIEnv)(envPtr)
defer freeFunc()
publicIDSign := util.ClassSign("com.veyron2.security.PublicID")
jID := C.jobject(util.CallObjectMethodOrCatch(env, c.jContext, "remoteID", nil, publicIDSign))
idPtr := util.CallLongMethodOrCatch(env, jID, "getNativePtr", nil)
return (*(*security.PublicID)(util.Ptr(idPtr)))
}
func (c *context) LocalEndpoint() naming.Endpoint {
envPtr, freeFunc := util.GetEnv(c.jVM)
env := (*C.JNIEnv)(envPtr)
defer freeFunc()
// TODO(spetrovic): create a Java Endpoint interface.
epStr := util.CallStringMethodOrCatch(env, c.jContext, "localEndpoint", nil)
ep, err := inaming.NewEndpoint(epStr)
if err != nil {
panic("Couldn't parse endpoint string: " + epStr)
}
return ep
}
func (c *context) RemoteEndpoint() naming.Endpoint {
envPtr, freeFunc := util.GetEnv(c.jVM)
env := (*C.JNIEnv)(envPtr)
defer freeFunc()
// TODO(spetrovic): create a Java Endpoint interface.
epStr := util.CallStringMethodOrCatch(env, c.jContext, "remoteEndpoint", nil)
ep, err := inaming.NewEndpoint(epStr)
if err != nil {
panic("Couldn't parse endpoint string: " + epStr)
}
return ep
}
func (c *context) callStringMethod(methodName string) string {
envPtr, freeFunc := util.GetEnv(c.jVM)
env := (*C.JNIEnv)(envPtr)
defer freeFunc()
return util.CallStringMethodOrCatch(env, c.jContext, methodName, nil)
}