Added stuff.

Change-Id: I1bb598ef0e869e9c1de030750412b4eb368ab37d
diff --git a/impl/google/discovery/jni.go b/impl/google/discovery/jni.go
index 354593a..49376d6 100644
--- a/impl/google/discovery/jni.go
+++ b/impl/google/discovery/jni.go
@@ -11,8 +11,13 @@
 	"encoding/binary"
 	"unsafe"
 
+	"v.io/v23"
+	"v.io/v23/discovery"
+	"v.io/v23/security"
+	idiscovery "v.io/x/ref/lib/discovery"
+
 	jutil "v.io/x/jni/util"
-	"v.io/x/ref/lib/discovery"
+	jcontext "v.io/x/jni/v23/context"
 )
 
 // #include "jni.h"
@@ -20,9 +25,26 @@
 import "C"
 
 var (
-	classSign = jutil.ClassSign("java.lang.Class")
+	updateSign = jutil.ClassSign("io.v.v23.discovery.Update")
+
+
 	// Global reference for java.util.UUID class;
 	jUUIDClass jutil.Class
+
+	// Global reference io.v.impl.google.lib.discovery.ScanHandler
+	jScanHandlerClass jutil.Class
+
+	// Global reference io.v.v23.discovery.VDiscovery$DoneCallback
+	jServiceClass jutil.Class
+
+	// Global reference io.v.v23.security.BlessingPattern
+	jBlessingPatternClass jutil.Class
+
+	// Global reference io.v.impl.google.lib.discovery.VDiscoveryImpl
+	jVDiscoveryImplClass jutil.Class
+
+	// Global reference io.v.v23.discovery.Update
+	jUpdateClass jutil.Class
 )
 
 // Init initializes the JNI code with the given Java environment. This method
@@ -33,11 +55,35 @@
 	// thread, so we aren't able to invoke FindClass in other threads.
 	var err error
 	jUUIDClass, err = jutil.JFindClass(env, "java/util/UUID")
+	if err != nil {
+		return err
+	}
 
+	jScanHandlerClass, err = jutil.JFindClass(env, "io/v/impl/google/lib/discovery/ScanHandler")
+	if err != nil {
+		return err
+	}
+
+	jServiceClass, err = jutil.JFindClass(env, "io/v/v23/discovery/Service")
+	if err != nil {
+		return err
+	}
+
+	jBlessingPatternClass, err = jutil.JFindClass(env, "io/v/v23/security/BlessingPattern")
+	if err != nil {
+		return err
+	}
+
+	jVDiscoveryImplClass, err = jutil.JFindClass(env, "io/v/impl/google/lib/discovery/VDiscoveryImpl")
+	if err != nil {
+		return err
+	}
+
+	jUpdateClass, err = jutil.JFindClass(env, "io/v/v23/discovery/Update")
 	return err
 }
 
-func convertStringtoUUID(jenv *C.JNIEnv, _ C.jclass, jName C.jstring, generator func(string) discovery.Uuid) C.jobject {
+func convertStringtoUUID(jenv *C.JNIEnv, _ C.jclass, jName C.jstring, generator func(string) idiscovery.Uuid) C.jobject {
 	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
 	name := jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
 	uuid := generator(name)
@@ -55,13 +101,151 @@
 
 //export Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForInterfaceName
 func Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForInterfaceName(jenv *C.JNIEnv, jclass C.jclass, jName C.jstring) C.jobject {
-	return convertStringtoUUID(jenv, jclass, jName, discovery.NewServiceUUID)
+	return convertStringtoUUID(jenv, jclass, jName, idiscovery.NewServiceUUID)
 }
 
 //export Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForAttributeKey
 func Java_io_v_impl_google_lib_discovery_UUIDUtil_UUIDForAttributeKey(jenv *C.JNIEnv, jclass C.jclass, jName C.jstring) C.jobject {
-	converter := func(s string) discovery.Uuid {
-		return discovery.Uuid(discovery.NewAttributeUUID(s))
+	converter := func(s string) idiscovery.Uuid {
+		return idiscovery.Uuid(idiscovery.NewAttributeUUID(s))
 	}
 	return convertStringtoUUID(jenv, jclass, jName, converter)
 }
+
+//export Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeCreate
+func Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeCreate(jenv *C.JNIEnv, jclass C.jclass, jContext C.jobject) C.jobject {
+	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
+	ctx, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
+	if err != nil {
+		jutil.JThrowV(env, err);
+		return C.jobject(unsafe.Pointer(jutil.NullObject))
+	}
+	d := v23.GetDiscovery(ctx)
+	ptrD := &d
+	jutil.GoRef(ptrD)
+	trigger := idiscovery.NewTrigger()
+	jutil.GoRef(trigger)
+
+	jDiscovery, err := jutil.NewObject(env, jVDiscoveryImplClass, []jutil.Sign{jutil.LongSign, jutil.LongSign}, int64(jutil.PtrValue(ptrD)), int64(jutil.PtrValue(trigger)))
+	if err != nil {
+		jutil.JThrowV(env, err);
+		return C.jobject(unsafe.Pointer(jutil.NullObject))
+	}
+	return C.jobject(unsafe.Pointer(jDiscovery))
+}
+
+//export Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeDelete
+func Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_nativeDelete(jenv *C.JNIEnv, _ C.jobject, discovery C.jlong, trigger C.jlong) {
+	jutil.GoUnref(jutil.NativePtr(discovery))
+	jutil.GoUnref(jutil.NativePtr(trigger))
+}
+
+//export Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_advertise
+func Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_advertise(jenv *C.JNIEnv, this C.jobject, jContext C.jobject, jService C.jobject, jPerms C.jobject, jCallback C.jobject) {
+	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
+	ctx, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
+	if err != nil {
+		return
+	}
+	servObject := jutil.Object(uintptr(unsafe.Pointer(jService)))
+	var service discovery.Service
+	if err := jutil.GoVomCopy(env, servObject, jServiceClass, &service); err != nil {
+		jutil.JThrowV(env, err)
+		return
+	}
+
+	permsArray, err := jutil.GoObjectList(env, jutil.Object(uintptr(unsafe.Pointer(jPerms))))
+	if err != nil {
+		jutil.JThrowV(env, err)
+		return
+	}
+	permsSlice := make([]security.BlessingPattern, len(permsArray))
+	for i, o := range permsArray {
+		if err := jutil.GoVomCopy(env, o, jBlessingPatternClass, &permsSlice[i]); err != nil {
+			jutil.JThrowV(env, err)
+			return
+		}
+	}
+	thisObject := jutil.Object(uintptr(unsafe.Pointer(this)))
+	discoveryPtr, err := jutil.JLongField(env, thisObject, "nativeDiscovery")
+	if err != nil {
+		jutil.JThrowV(env, err)
+		return
+	}
+
+	ds := *(*discovery.T)(jutil.NativePtr(jutil.Object(unsafe.Pointer(uintptr(discoveryPtr)))))
+
+	triggerPtr, err := jutil.JLongField(env, thisObject, "nativeTrigger")
+
+	if err != nil {
+		jutil.JThrowV(env, err)
+		return
+	}
+
+	trigger := (*idiscovery.Trigger)(jutil.NativePtr(jutil.Object(unsafe.Pointer(uintptr(triggerPtr)))))
+
+	done, err := ds.Advertise(ctx, service, permsSlice)
+
+	if err != nil {
+		jutil.JThrowV(env, err)
+		return
+	}
+	cb := jutil.Object(uintptr(unsafe.Pointer(jCallback)))
+	jutil.NewGlobalRef(env, cb)
+	trigger.Add(func() {
+		env, freeFunc := jutil.GetEnv()
+		defer freeFunc()
+		// TODO(bjornick): What should we do on errors?
+		if err := jutil.CallVoidMethod(env, cb, "done", []jutil.Sign{}); err != nil {
+			jutil.JThrowV(env, err)
+		}
+		jutil.DeleteGlobalRef(env, cb)
+	}, done)
+}
+
+//export Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_scan
+func Java_io_v_impl_google_lib_discovery_VDiscoveryImpl_scan(jenv *C.JNIEnv, this C.jobject, jContext C.jobject, jQuery C.jstring, jCallback C.jobject) {
+	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
+	ctx, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
+	if err != nil {
+		return
+	}
+	query := jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jQuery))))
+
+	thisObject := jutil.Object(uintptr(unsafe.Pointer(this)))
+	discoveryPtr, err := jutil.JLongField(env, thisObject, "nativeDiscovery")
+	if err != nil {
+		jutil.JThrowV(env, err)
+		return
+	}
+	ds := *(*discovery.T)(jutil.NativePtr(jutil.Object(unsafe.Pointer(uintptr(discoveryPtr)))))
+
+	updates, err := ds.Scan(ctx, query)
+
+	jutil.NewGlobalRef(env, jutil.Object(uintptr(unsafe.Pointer(jCallback))))
+	if err != nil {
+		jutil.JThrowV(env, err)
+		return
+	}
+	cb := jutil.Object(uintptr(unsafe.Pointer(jCallback)))
+	jutil.NewGlobalRef(env, cb)
+	go func() {
+		env, freeFunc := jutil.GetEnv()
+		defer freeFunc()
+		for v := range updates {
+			jUpdate, err := jutil.JVomCopy(env, v, jUpdateClass)
+			if err != nil {
+				ctx.Errorf("Failed to convert update: %v", err)
+				continue
+			}
+			err = jutil.CallVoidMethod(env, cb, "handleUpdate", []jutil.Sign{updateSign}, jUpdate)
+			if err != nil {
+				ctx.Errorf("Failed to call handler: %v", err)
+				continue
+			}
+		}
+		jutil.DeleteGlobalRef(env, cb)
+	}()
+}
+
+
diff --git a/jni.go b/jni.go
index 05f915d..9168811 100644
--- a/jni.go
+++ b/jni.go
@@ -7,6 +7,10 @@
 package jni
 
 import (
+	"unsafe"
+
+	jutil "v.io/x/jni/util"
+
 	_ "v.io/x/ref/runtime/factories/roaming"
 )
 
diff --git a/libs/discovery/jni.go b/libs/discovery/jni.go
index 7b94e55..808af88 100644
--- a/libs/discovery/jni.go
+++ b/libs/discovery/jni.go
@@ -58,7 +58,7 @@
 	}
 	advObject := jutil.Object(uintptr(unsafe.Pointer(jAdv)))
 	var adv discovery.Advertisement
-	if err := jutil.GoVomCopy(env, advObject, jAdvertisementClass, adv); err != nil {
+	if err := jutil.GoVomCopy(env, advObject, jAdvertisementClass, &adv); err != nil {
 		jutil.JThrow(env, err)
 		return
 	}
diff --git a/shared.go b/shared.go
index 55f1a04..7832b4a 100644
--- a/shared.go
+++ b/shared.go
@@ -8,7 +8,6 @@
 
 import (
 	"os"
-	"unsafe"
 
 	"v.io/x/lib/vlog"
 
@@ -38,7 +37,6 @@
 }
 
 func setupV23(env jutil.Env) {
-	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
 	if err := jv23.Init(env); err != nil {
 		jutil.JThrowV(env, err)
 		return