v.io/x/jni: JNI support for new Java server api

MultiPart: 2/2
Change-Id: I7020687efaf26000cccbb6e9a2dd1da880d53305
diff --git a/impl/google/namespace/util.go b/impl/google/namespace/util.go
index 46974a0..46a04c8 100644
--- a/impl/google/namespace/util.go
+++ b/impl/google/namespace/util.go
@@ -19,6 +19,9 @@
 // JavaNamespace converts the provided Go Namespace into a Java Namespace
 // object.
 func JavaNamespace(env jutil.Env, namespace namespace.T) (jutil.Object, error) {
+	if namespace == nil {
+		return jutil.NullObject, nil
+	}
 	jNamespace, err := jutil.NewObject(env, jNamespaceImplClass, []jutil.Sign{jutil.LongSign}, int64(jutil.PtrValue(&namespace)))
 	if err != nil {
 		return jutil.NullObject, err
diff --git a/impl/google/rpc/util.go b/impl/google/rpc/util.go
index b463d33..1067dde 100644
--- a/impl/google/rpc/util.go
+++ b/impl/google/rpc/util.go
@@ -34,7 +34,7 @@
 // JavaClient converts the provided Go client into a Java Client object.
 func JavaClient(env jutil.Env, client rpc.Client) (jutil.Object, error) {
 	if client == nil {
-		return jutil.NullObject, fmt.Errorf("Go Client value cannot be nil")
+		return jutil.NullObject, nil
 	}
 	jClient, err := jutil.NewObject(env, jClientImplClass, []jutil.Sign{jutil.LongSign}, int64(jutil.PtrValue(&client)))
 	if err != nil {
diff --git a/impl/google/rt/jni.go b/impl/google/rt/jni.go
index 15493e7..91c002e 100644
--- a/impl/google/rt/jni.go
+++ b/impl/google/rt/jni.go
@@ -13,6 +13,7 @@
 	"v.io/v23"
 	"v.io/v23/context"
 	_ "v.io/x/ref/runtime/factories/roaming"
+	"v.io/v23/rpc"
 
 	jns "v.io/x/jni/impl/google/namespace"
 	jrpc "v.io/x/jni/impl/google/rpc"
@@ -33,6 +34,7 @@
 }
 
 type shutdownKey struct{}
+type serverKey struct{}
 
 //export Java_io_v_impl_google_rt_VRuntimeImpl_nativeInit
 func Java_io_v_impl_google_rt_VRuntimeImpl_nativeInit(jenv *C.JNIEnv, jRuntime C.jclass, jNumCpus C.jint) C.jobject {
@@ -61,8 +63,8 @@
 	}
 }
 
-//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeSetNewClient
-func Java_io_v_impl_google_rt_VRuntimeImpl_nativeSetNewClient(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject, jOptions C.jobject) C.jobject {
+//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeWithNewClient
+func Java_io_v_impl_google_rt_VRuntimeImpl_nativeWithNewClient(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject, jOptions C.jobject) C.jobject {
 	env := jutil.WrapEnv(jenv)
 	// TODO(spetrovic): Have Java context support nativePtr()?
 	ctx, err := jcontext.GoContext(env, jutil.WrapObject(jContext))
@@ -102,8 +104,8 @@
 	return C.jobject(unsafe.Pointer(jClient))
 }
 
-//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeNewServer
-func Java_io_v_impl_google_rt_VRuntimeImpl_nativeNewServer(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject, jName C.jstring, jDispatcher C.jobject) C.jobject {
+//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeWithNewServer
+func Java_io_v_impl_google_rt_VRuntimeImpl_nativeWithNewServer(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject, jName C.jstring, jDispatcher C.jobject) C.jobject {
 	env := jutil.WrapEnv(jenv)
 	// TODO(spetrovic): Have Java context support nativePtr()?
 	ctx, err := jcontext.GoContext(env, jutil.WrapObject(jContext))
@@ -117,12 +119,36 @@
 		jutil.JThrowV(env, err)
 		return nil
 	}
-	// TODO(mattr): This should be returning the new context returned here.
-	_, server, err := v23.WithNewDispatchingServer(ctx, name, d)
+	newCtx, server, err := v23.WithNewDispatchingServer(ctx, name, d)
 	if err != nil {
 		jutil.JThrowV(env, err)
 		return nil
 	}
+	// Explicitly attach a server to the new context.
+	serverAttCtx := context.WithValue(newCtx, serverKey{}, server)
+	jServerAttCtx, err := jcontext.JavaContext(env, serverAttCtx, nil)
+	if err != nil {
+		jutil.JThrowV(env, err)
+		return nil
+	}
+	return C.jobject(unsafe.Pointer(jServerAttCtx))
+}
+
+//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeGetServer
+func Java_io_v_impl_google_rt_VRuntimeImpl_nativeGetServer(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject) C.jobject {
+	env := jutil.WrapEnv(jenv)
+	// TODO(spetrovic): Have Java context support nativePtr()?
+	ctx, err := jcontext.GoContext(env, jutil.WrapObject(jContext))
+	if err != nil {
+		jutil.JThrowV(env, err)
+		return nil
+	}
+	// Get the server we attached to the context.
+	value := ctx.Value(serverKey{})
+	server, ok := value.(rpc.Server)
+	if !ok {
+		server = nil
+	}
 	jServer, err := jrpc.JavaServer(env, server)
 	if err != nil {
 		jutil.JThrowV(env, err)
@@ -131,8 +157,8 @@
 	return C.jobject(unsafe.Pointer(jServer))
 }
 
-//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeSetPrincipal
-func Java_io_v_impl_google_rt_VRuntimeImpl_nativeSetPrincipal(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject, jPrincipal C.jobject) C.jobject {
+//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeWithPrincipal
+func Java_io_v_impl_google_rt_VRuntimeImpl_nativeWithPrincipal(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject, jPrincipal C.jobject) C.jobject {
 	env := jutil.WrapEnv(jenv)
 	// TODO(spetrovic): Have Java context support nativePtr()?
 	ctx, err := jcontext.GoContext(env, jutil.WrapObject(jContext))
@@ -176,8 +202,8 @@
 	return C.jobject(unsafe.Pointer(jPrincipal))
 }
 
-//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeSetNamespace
-func Java_io_v_impl_google_rt_VRuntimeImpl_nativeSetNamespace(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject, jRoots C.jobjectArray) C.jobject {
+//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeWithNamespace
+func Java_io_v_impl_google_rt_VRuntimeImpl_nativeWithNamespace(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject, jRoots C.jobjectArray) C.jobject {
 	env := jutil.WrapEnv(jenv)
 	// TODO(spetrovic): Have Java context support nativePtr()?
 	ctx, err := jcontext.GoContext(env, jutil.WrapObject(jContext))
@@ -222,25 +248,8 @@
 	return C.jobject(unsafe.Pointer(jNamespace))
 }
 
-//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeGetListenSpec
-func Java_io_v_impl_google_rt_VRuntimeImpl_nativeGetListenSpec(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject) C.jobject {
-	env := jutil.WrapEnv(jenv)
-	ctx, err := jcontext.GoContext(env, jutil.WrapObject(jContext))
-	if err != nil {
-		jutil.JThrowV(env, err)
-		return nil
-	}
-	spec := v23.GetListenSpec(ctx)
-	jSpec, err := jrpc.JavaListenSpec(env, spec)
-	if err != nil {
-		jutil.JThrowV(env, err)
-		return nil
-	}
-	return C.jobject(unsafe.Pointer(jSpec))
-}
-
-//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeSetListenSpec
-func Java_io_v_impl_google_rt_VRuntimeImpl_nativeSetListenSpec(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject, jSpec C.jobject) C.jobject {
+//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeWithListenSpec
+func Java_io_v_impl_google_rt_VRuntimeImpl_nativeWithListenSpec(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject, jSpec C.jobject) C.jobject {
 	env := jutil.WrapEnv(jenv)
 	ctx, err := jcontext.GoContext(env, jutil.WrapObject(jContext))
 	if err != nil {
@@ -260,3 +269,20 @@
 	}
 	return C.jobject(unsafe.Pointer(jNewCtx))
 }
+
+//export Java_io_v_impl_google_rt_VRuntimeImpl_nativeGetListenSpec
+func Java_io_v_impl_google_rt_VRuntimeImpl_nativeGetListenSpec(jenv *C.JNIEnv, jRuntime C.jclass, jContext C.jobject) C.jobject {
+	env := jutil.WrapEnv(jenv)
+	ctx, err := jcontext.GoContext(env, jutil.WrapObject(jContext))
+	if err != nil {
+		jutil.JThrowV(env, err)
+		return nil
+	}
+	spec := v23.GetListenSpec(ctx)
+	jSpec, err := jrpc.JavaListenSpec(env, spec)
+	if err != nil {
+		jutil.JThrowV(env, err)
+		return nil
+	}
+	return C.jobject(unsafe.Pointer(jSpec))
+}
\ No newline at end of file