veyron/runtimes/google/security/jni: Hookup Java security into main ipc flow.

Change-Id: I318f25c16dd6bd3a9433a18b7ad551b626ab62a9
diff --git a/runtimes/google/ipc/jni/dispatcher.go b/runtimes/google/ipc/jni/dispatcher.go
index 425a6fb..2e5174e 100644
--- a/runtimes/google/ipc/jni/dispatcher.go
+++ b/runtimes/google/ipc/jni/dispatcher.go
@@ -7,6 +7,7 @@
 	"runtime"
 
 	"veyron/runtimes/google/jni/util"
+	isecurity "veyron/runtimes/google/security/jni"
 	"veyron2/ipc"
 	"veyron2/security"
 )
@@ -15,9 +16,15 @@
 // #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) {
+// static jobject CallDispatcherLookupMethod(JNIEnv* env, jobject obj, jmethodID id, jstring str) {
 //   return (*env)->CallObjectMethod(env, obj, id, str);
 // }
+// static jobject CallDispatcherGetObjectMethod(JNIEnv* env, jobject obj, jmethodID id) {
+//   return (*env)->CallObjectMethod(env, obj, id);
+// }
+// static jobject CallDispatcherGetAuthorizerMethod(JNIEnv* env, jobject obj, jmethodID id) {
+//   return (*env)->CallObjectMethod(env, obj, id);
+// }
 import "C"
 
 func newDispatcher(env *C.JNIEnv, jDispatcher C.jobject) (*dispatcher, error) {
@@ -58,21 +65,36 @@
 	defer C.DetachCurrentThread(d.jVM)
 
 	// Call Java dispatcher's lookup() method.
-	lid := C.jmethodID(util.JMethodIDPtrOrDie(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)))
+	serviceObjectWithAuthorizerSign := "Lcom/veyron2/ipc/ServiceObjectWithAuthorizer;"
+	lid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, d.jDispatcher), "lookup", fmt.Sprintf("(%s)%s", util.StringSign, serviceObjectWithAuthorizerSign)))
+	jServiceObjectWithAuthorizer := C.CallDispatcherLookupMethod(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.
+	if jServiceObjectWithAuthorizer == nil {
+		// Lookup returned null, which means that the dispatcher isn't handling the object -
+		// this is not an error.
 		return nil, nil, nil
 	}
+
+	// Extract the Java service object and Authorizer.
+	oid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, jServiceObjectWithAuthorizer), "getServiceObject", fmt.Sprintf("()%s", util.ObjectSign)))
+	jObj := C.CallDispatcherGetObjectMethod(env, jServiceObjectWithAuthorizer, oid)
+	if jObj == nil {
+		return nil, nil, fmt.Errorf("null service object returned by Java's ServiceObjectWithAuthorizer")
+	}
+	authSign := "Lcom/veyron2/security/Authorizer;"
+	aid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, jServiceObjectWithAuthorizer), "getAuthorizer", fmt.Sprintf("()%s", authSign)))
+	jAuth := C.CallDispatcherGetAuthorizerMethod(env, jServiceObjectWithAuthorizer, aid)
+
+	// Create Go Invoker and Authorizer.
 	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
+	var a security.Authorizer
+	if jAuth != nil {
+		a = isecurity.NewAuthorizer(env, jAuth)
+	}
+	return i, a, nil
 }
diff --git a/runtimes/google/ipc/jni/invoker.go b/runtimes/google/ipc/jni/invoker.go
index 0cda728..90368a0 100644
--- a/runtimes/google/ipc/jni/invoker.go
+++ b/runtimes/google/ipc/jni/invoker.go
@@ -20,30 +20,33 @@
 //
 // // CGO doesn't support variadic functions so we have to hard-code these
 // // functions to match the invoking code. Ugh!
-// static jobject CallInvokeMethod(JNIEnv* env, jobject obj, jmethodID id, jstring method, jobject call, jobjectArray inArgs) {
-//   return (*env)->CallObjectMethod(env, obj, id, method, call, inArgs);
+// static jobject CallInvokerInvokeMethod(JNIEnv* env, jobject obj, jmethodID id, jstring method, jobject call, jobjectArray inArgs) {
+// 	return (*env)->CallObjectMethod(env, obj, id, method, call, inArgs);
 // }
-// static jobject CallNewInvokerObject(JNIEnv* env, jclass class, jmethodID id, jobject obj) {
-//   return (*env)->NewObject(env, class, id, obj);
+// static jobject CallInvokerNewInvokerObject(JNIEnv* env, jclass class, jmethodID id, jobject obj) {
+// 	return (*env)->NewObject(env, class, id, obj);
 // }
-// static jobject CallGetInterfacePath(JNIEnv* env, jobject obj, jmethodID id) {
-//   return (*env)->CallObjectMethod(env, obj, id);
+// static jobject CallInvokerGetInterfacePath(JNIEnv* env, jobject obj, jmethodID id) {
+// 	return (*env)->CallObjectMethod(env, obj, id);
 // }
-// static jobject CallNewServerCallObject(JNIEnv* env, jclass class, jmethodID id, jlong ref) {
-//   return (*env)->NewObject(env, class, id, ref);
+// static jobject CallInvokerGetSecurityLabelMethod(JNIEnv* env, jobject obj, jmethodID id, jstring method) {
+// 	return (*env)->CallObjectMethod(env, obj, id, method);
+// }
+// static jobject CallInvokerNewServerCallObject(JNIEnv* env, jclass class, jmethodID id, jlong ref) {
+// 	return (*env)->NewObject(env, class, id, ref);
 // }
 import "C"
 
 func newInvoker(env *C.JNIEnv, jVM *C.JavaVM, jObj C.jobject) (*invoker, error) {
 	// Create a new Java VDLInvoker object.
 	cid := C.jmethodID(util.JMethodIDPtrOrDie(env, jVDLInvokerClass, "<init>", fmt.Sprintf("(%s)%s", util.ObjectSign, util.VoidSign)))
-	jInvoker := C.CallNewInvokerObject(env, jVDLInvokerClass, cid, jObj)
+	jInvoker := C.CallInvokerNewInvokerObject(env, jVDLInvokerClass, cid, jObj)
 	if err := util.JExceptionMsg(env); err != nil {
 		return nil, fmt.Errorf("error creating Java VDLInvoker object: %v", err)
 	}
 	// Fetch the argGetter for the object.
 	pid := C.jmethodID(util.JMethodIDPtrOrDie(env, jVDLInvokerClass, "getImplementedServices", fmt.Sprintf("()%s", util.ArraySign(util.StringSign))))
-	jPathArray := C.jobjectArray(C.CallGetInterfacePath(env, jInvoker, pid))
+	jPathArray := C.jobjectArray(C.CallInvokerGetInterfacePath(env, jInvoker, pid))
 	paths := util.GoStringArray(env, jPathArray)
 	getter, err := newArgGetter(paths)
 	if err != nil {
@@ -79,14 +82,28 @@
 	// arguments into vom.Value objects, which we shall then de-serialize into
 	// Java objects (see Invoke comments below).  This approach is blocked on
 	// pending VOM encoder/decoder changes as well as Java (de)serializer.
+	var env *C.JNIEnv
+	C.AttachCurrentThread(i.jVM, &env, nil)
+	defer C.DetachCurrentThread(i.jVM)
+
 	mArgs := i.argGetter.FindMethod(method, numArgs)
 	if mArgs == nil {
 		err = fmt.Errorf("couldn't find VDL method %q with %d args", method, numArgs)
 		return
 	}
 	argptrs = mArgs.InPtrs()
-	// TODO(spetrovic): ask the Java object to give us the label.
-	label = security.AdminLabel
+
+	// Get the security label.
+	labelSign := "Lcom/veyron2/security/Label;"
+	mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, i.jInvoker), "getSecurityLabel", fmt.Sprintf("(%s)%s", util.StringSign, labelSign)))
+	if err = util.JExceptionMsg(env); err != nil {
+		return
+	}
+	jLabel := C.CallInvokerGetSecurityLabelMethod(env, i.jInvoker, mid, C.jstring(util.JStringPtr(env, util.CamelCase(method))))
+	if err = util.JExceptionMsg(env); err != nil {
+		return
+	}
+	label = security.Label(util.JIntField(env, jLabel, "value"))
 	return
 }
 
@@ -109,7 +126,7 @@
 	}
 	sCall := newServerCall(call, mArgs)
 	cid := C.jmethodID(util.JMethodIDPtrOrDie(env, jServerCallClass, "<init>", fmt.Sprintf("(%s)%s", util.LongSign, util.VoidSign)))
-	jServerCall := C.CallNewServerCallObject(env, jServerCallClass, cid, C.jlong(util.PtrValue(sCall)))
+	jServerCall := C.CallInvokerNewServerCallObject(env, jServerCallClass, cid, C.jlong(util.PtrValue(sCall)))
 	util.GoRef(sCall) // unref-ed when jServerCall is garbage-collected
 
 	// Translate input args to JSON.
@@ -121,7 +138,7 @@
 	const callSign = "Lcom/veyron2/ipc/ServerCall;"
 	const replySign = "Lcom/veyron/runtimes/google/VDLInvoker$InvokeReply;"
 	mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, i.jInvoker), "invoke", fmt.Sprintf("(%s%s[%s)%s", util.StringSign, callSign, util.StringSign, replySign)))
-	jReply := C.CallInvokeMethod(env, i.jInvoker, mid, C.jstring(util.JStringPtr(env, util.CamelCase(method))), jServerCall, jArgs)
+	jReply := C.CallInvokerInvokeMethod(env, i.jInvoker, mid, C.jstring(util.JStringPtr(env, util.CamelCase(method))), jServerCall, jArgs)
 	if err := util.JExceptionMsg(env); err != nil {
 		return nil, fmt.Errorf("error invoking Java method %q: %v", method, err)
 	}
diff --git a/runtimes/google/ipc/jni/jni.go b/runtimes/google/ipc/jni/jni.go
index 36c5b90..e8bcb8e 100644
--- a/runtimes/google/ipc/jni/jni.go
+++ b/runtimes/google/ipc/jni/jni.go
@@ -159,8 +159,8 @@
 	}
 }
 
-//export Java_com_veyron_runtimes_google_jni_Runtime_00024Server_nativeFinalize
-func Java_com_veyron_runtimes_google_jni_Runtime_00024Server_nativeFinalize(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong) {
+//export Java_com_veyron_runtimes_google_Runtime_00024Server_nativeFinalize
+func Java_com_veyron_runtimes_google_Runtime_00024Server_nativeFinalize(env *C.JNIEnv, server C.jobject, goServerPtr C.jlong) {
 	util.GoUnref((*ipc.Server)(util.Ptr(goServerPtr)))
 }
 
diff --git a/runtimes/google/jni/util/util.go b/runtimes/google/jni/util/util.go
index 767d62c..ce19623 100644
--- a/runtimes/google/jni/util/util.go
+++ b/runtimes/google/jni/util/util.go
@@ -43,6 +43,8 @@
 	StringSign = "Ljava/lang/String;"
 	// ObjectSign denotes a signature of a Java Object type.
 	ObjectSign = "Ljava/lang/Object;"
+	// ClassSign denotes a signature of a Java Class type.
+	ClassSign = "Ljava/lang/Class;"
 )
 
 // ArraySign returns the array signature, given the underlying array type.
diff --git a/runtimes/google/security/jni/authorizer.go b/runtimes/google/security/jni/authorizer.go
index e1bf576..7536894 100644
--- a/runtimes/google/security/jni/authorizer.go
+++ b/runtimes/google/security/jni/authorizer.go
@@ -70,10 +70,6 @@
 	// Run Java Authorizer.
 	contextSign := "Lcom/veyron2/security/Context;"
 	mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, a.jAuth), "authorize", fmt.Sprintf("(%s)%s", contextSign, util.VoidSign)))
-	if mid == nil {
-		return fmt.Errorf("Srdjan's error")
-	}
-	return nil
 	C.CallAuthorizerAuthorizeMethod(env, a.jAuth, mid, jContext)
 	if err := util.JExceptionMsg(env); err != nil {
 		return err
diff --git a/runtimes/google/security/jni/caveat.go b/runtimes/google/security/jni/caveat.go
index b09885a..0b44f75 100644
--- a/runtimes/google/security/jni/caveat.go
+++ b/runtimes/google/security/jni/caveat.go
@@ -59,7 +59,7 @@
 	defer C.DetachCurrentThread(c.jVM)
 	util.GoRef(&context) // un-refed when the Java Context object is finalized.
 	cid := C.jmethodID(util.JMethodIDPtrOrDie(env, jContextImplClass, "<init>", fmt.Sprintf("(%s)%s", util.LongSign, util.VoidSign)))
-	jContext := C.CallCaveatNewContextObject(env, jContextClass, cid, C.jlong(util.PtrValue(&context)))
+	jContext := C.CallCaveatNewContextObject(env, jContextImplClass, cid, C.jlong(util.PtrValue(&context)))
 	contextSign := "Lcom/veyron2/security/Context;"
 	mid := C.jmethodID(util.JMethodIDPtrOrDie(env, C.GetObjectClass(env, c.jCaveat), "validate", fmt.Sprintf("(%s)%s", contextSign, util.VoidSign)))
 	C.CallCaveatValidateMethod(env, c.jCaveat, mid, jContext)
diff --git a/runtimes/google/security/jni/context.go b/runtimes/google/security/jni/context.go
index 533f2d9..8b63eec 100644
--- a/runtimes/google/security/jni/context.go
+++ b/runtimes/google/security/jni/context.go
@@ -26,6 +26,9 @@
 // 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 {
@@ -86,8 +89,10 @@
 	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), "label", fmt.Sprintf("()%s", util.IntSign)))
-	return security.Label(C.CallContextIntMethod(env, c.jContext, mid))
+	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 {
diff --git a/runtimes/google/security/jni/jni.go b/runtimes/google/security/jni/jni.go
index 2e50950..458d414 100644
--- a/runtimes/google/security/jni/jni.go
+++ b/runtimes/google/security/jni/jni.go
@@ -5,6 +5,7 @@
 import (
 	"encoding/asn1"
 	"fmt"
+	"reflect"
 	"time"
 	"unsafe"
 
@@ -38,8 +39,6 @@
 	jCaveatImplClass C.jclass
 	// Global reference for com.veyron.runtimes.google.security.Context class.
 	jContextImplClass C.jclass
-	// Global reference for com.veyron2.security.Context class.
-	jContextClass C.jclass
 	// Global reference for com.veyron2.security.Caveat class.
 	jCaveatClass C.jclass
 	// Global reference for com.veyron2.security.ServiceCaveat class.
@@ -59,7 +58,6 @@
 	jPublicIDImplClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron/runtimes/google/security/PublicID"))
 	jECPublicKeyInfoClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron/runtimes/google/security/PublicID$ECPublicKeyInfo"))
 	jCaveatImplClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron/runtimes/google/security/Caveat"))
-	jContextClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron2/security/Context"))
 	jContextImplClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron/runtimes/google/security/Context"))
 	jCaveatClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron2/security/Caveat"))
 	jServiceCaveatClass = C.jclass(util.JFindClassPtrOrDie(env, "com/veyron2/security/ServiceCaveat"))
@@ -118,6 +116,16 @@
 	return jServiceCaveats
 }
 
+//export Java_com_veyron_runtimes_google_security_PublicID_nativeEquals
+func Java_com_veyron_runtimes_google_security_PublicID_nativeEquals(env *C.JNIEnv, jPublicID C.jobject, goPublicIDPtr, goOtherPublicIDPtr C.jlong) C.jboolean {
+	id := *(*security.PublicID)(util.Ptr(goPublicIDPtr))
+	other := *(*security.PublicID)(util.Ptr(goOtherPublicIDPtr))
+	if reflect.DeepEqual(id, other) {
+		return C.JNI_TRUE
+	}
+	return C.JNI_FALSE
+}
+
 //export Java_com_veyron_runtimes_google_security_PublicID_nativeFinalize
 func Java_com_veyron_runtimes_google_security_PublicID_nativeFinalize(env *C.JNIEnv, jPublicID C.jobject, goPublicIDPtr C.jlong) {
 	util.GoUnref((*security.PublicID)(util.Ptr(goPublicIDPtr)))