java: Implement 6 more JNI syncbase internal functions

The functions added in this CL are:

  Service.GetPermissions
  Service.SetPermissions
  Database.GetPermissions
  Database.SetPermissions
  Collection.GetPermissions
  Collection.SetPermissions

This CL also makes the newVBytesFromJava more resilient (works when a
nil is passed in) and reorders the bottom part of the jni.go to be in
alphabetical order of the v23_syncbase_ types they are operating on.

MultiPart: 1/2
Change-Id: Ia05bcd78f71c1f4f975868d9bce6595816ddc10d
diff --git a/services/syncbase/bridge/cgo/jni.go b/services/syncbase/bridge/cgo/jni.go
index 27b8d5d..cf2e13f 100644
--- a/services/syncbase/bridge/cgo/jni.go
+++ b/services/syncbase/bridge/cgo/jni.go
@@ -32,9 +32,11 @@
 	arrayListClass              jArrayListClass
 	hashMapClass                jHashMap
 	idClass                     jIdClass
+	permissionsClass            jPermissions
 	syncgroupMemberInfoClass    jSyncgroupMemberInfo
 	syncgroupSpecClass          jSyncgroupSpec
 	verrorClass                 jVErrorClass
+	versionedPermissionsClass   jVersionedPermissions
 	versionedSyncgroupSpecClass jVersionedSyncgroupSpec
 )
 
@@ -56,18 +58,35 @@
 	arrayListClass = newJArrayListClass(env)
 	hashMapClass = newJHashMap(env)
 	idClass = newJIdClass(env)
+	permissionsClass = newJPermissions(env)
 	syncgroupMemberInfoClass = newJSyncgroupMemberInfo(env)
 	syncgroupSpecClass = newJSyncgroupSpec(env)
 	verrorClass = newJVErrorClass(env)
+	versionedPermissionsClass = newJVersionedPermissions(env)
 	versionedSyncgroupSpecClass = newJVersionedSyncgroupSpec(env)
 
 	return C.JNI_VERSION_1_6
 }
 
+//export Java_io_v_syncbase_internal_Service_GetPermissions
 func Java_io_v_syncbase_internal_Service_GetPermissions(env *C.JNIEnv, cls C.jclass) C.jobject {
-	return nil
+	var cPerms C.v23_syncbase_Permissions
+	var cVersion C.v23_syncbase_String
+	var cErr C.v23_syncbase_VError
+	v23_syncbase_ServiceGetPermissions(&cPerms, &cVersion, &cErr)
+	if maybeThrowException(env, &cErr) {
+		return nil
+	}
+	return newVersionedPermissions(env, &cPerms, &cVersion)
 }
-func Java_io_v_syncbase_internal_Service_SetPermissions(env *C.JNIEnv, cls C.jclass, obj C.jobject) {}
+
+//export Java_io_v_syncbase_internal_Service_SetPermissions
+func Java_io_v_syncbase_internal_Service_SetPermissions(env *C.JNIEnv, cls C.jclass, obj C.jobject) {
+	cPerms, cVersion := newVPermissionsAndVersionFromJava(env, obj)
+	var cErr C.v23_syncbase_VError
+	v23_syncbase_ServiceSetPermissions(cPerms, cVersion, &cErr)
+	maybeThrowException(env, &cErr)
+}
 
 //export Java_io_v_syncbase_internal_Service_ListDatabases
 func Java_io_v_syncbase_internal_Service_ListDatabases(env *C.JNIEnv, cls C.jclass) C.jobject {
@@ -79,10 +98,26 @@
 	return obj
 }
 
+//export Java_io_v_syncbase_internal_Database_GetPermissions
 func Java_io_v_syncbase_internal_Database_GetPermissions(env *C.JNIEnv, cls C.jclass, name C.jstring) C.jobject {
-	return nil
+	cName := newVStringFromJava(env, name)
+	var cPerms C.v23_syncbase_Permissions
+	var cVersion C.v23_syncbase_String
+	var cErr C.v23_syncbase_VError
+	v23_syncbase_DbGetPermissions(cName, &cPerms, &cVersion, &cErr)
+	if maybeThrowException(env, &cErr) {
+		return nil
+	}
+	return newVersionedPermissions(env, &cPerms, &cVersion)
 }
-func Java_io_v_syncbase_internal_Database_SetPermissions(env *C.JNIEnv, cls C.jclass, name C.jstring, perms C.jobject) {
+
+//export Java_io_v_syncbase_internal_Database_SetPermissions
+func Java_io_v_syncbase_internal_Database_SetPermissions(env *C.JNIEnv, cls C.jclass, name C.jstring, obj C.jobject) {
+	cName := newVStringFromJava(env, name)
+	cPerms, cVersion := newVPermissionsAndVersionFromJava(env, obj)
+	var cErr C.v23_syncbase_VError
+	v23_syncbase_DbSetPermissions(cName, cPerms, cVersion, &cErr)
+	maybeThrowException(env, &cErr)
 }
 
 // maybeThrowException takes ownership of cErr and throws a Java exception if
@@ -289,10 +324,27 @@
 func Java_io_v_syncbase_internal_Database_WatchPatterns(env *C.JNIEnv, cls C.jclass, name C.jstring, resumeMaker C.jbyteArray, patters C.jobject, callbacks C.jobject) {
 }
 
+//export Java_io_v_syncbase_internal_Collection_GetPermissions
 func Java_io_v_syncbase_internal_Collection_GetPermissions(env *C.JNIEnv, cls C.jclass, name C.jstring, handle C.jstring) C.jobject {
-	return nil
+	cName := newVStringFromJava(env, name)
+	cHandle := newVStringFromJava(env, handle)
+	var cPerms C.v23_syncbase_Permissions
+	var cErr C.v23_syncbase_VError
+	v23_syncbase_CollectionGetPermissions(cName, cHandle, &cPerms, &cErr)
+	if maybeThrowException(env, &cErr) {
+		return nil
+	}
+	return cPerms.extractToJava(env)
 }
+
+//export Java_io_v_syncbase_internal_Collection_SetPermissions
 func Java_io_v_syncbase_internal_Collection_SetPermissions(env *C.JNIEnv, cls C.jclass, name C.jstring, handle C.jstring, perms C.jobject) {
+	cName := newVStringFromJava(env, name)
+	cHandle := newVStringFromJava(env, handle)
+	cPerms := newVPermissionsFromJava(env, perms)
+	var cErr C.v23_syncbase_VError
+	v23_syncbase_CollectionSetPermissions(cName, cHandle, cPerms, &cErr)
+	maybeThrowException(env, &cErr)
 }
 
 //export Java_io_v_syncbase_internal_Collection_Create
@@ -488,6 +540,21 @@
 	return obj
 }
 
+func (x *C.v23_syncbase_Permissions) extractToJava(env *C.JNIEnv) C.jobject {
+	obj := C.NewObjectA(env, permissionsClass.class, permissionsClass.init, nil)
+	C.SetObjectField(env, obj, permissionsClass.json, x.json.extractToJava(env))
+	return obj
+}
+
+// newVersionedPermissions extracts a VersionedPermissions object from a
+// v23_syncbase_Permissions and a v23_syncbase_String version.
+func newVersionedPermissions(env *C.JNIEnv, cPerms *C.v23_syncbase_Permissions, cVersion *C.v23_syncbase_String) C.jobject {
+	obj := C.NewObjectA(env, versionedPermissionsClass.class, versionedPermissionsClass.init, nil)
+	C.SetObjectField(env, obj, versionedPermissionsClass.version, cVersion.extractToJava(env))
+	C.SetObjectField(env, obj, versionedPermissionsClass.permissions, cPerms.extractToJava(env))
+	return obj
+}
+
 // newVStringsFromJava creates a v23_syncbase_Strings from a List<String>.
 func newVStringsFromJava(env *C.JNIEnv, obj C.jobject) C.v23_syncbase_Strings {
 	if obj == nil {
@@ -520,14 +587,14 @@
 	return r
 }
 
-func (x *C.v23_syncbase_SyncgroupSpec) extractToJava(env *C.JNIEnv) C.jobject {
-	obj := C.NewObjectA(env, syncgroupSpecClass.class, syncgroupSpecClass.init, nil)
-	C.SetObjectField(env, obj, syncgroupSpecClass.description, x.description.extractToJava(env))
-	C.SetObjectField(env, obj, syncgroupSpecClass.publishSyncbaseName, x.publishSyncbaseName.extractToJava(env))
-	// TODO(razvanm): Also extract the permissions.
-	C.SetObjectField(env, obj, syncgroupSpecClass.collections, x.collections.extractToJava(env))
-	C.SetObjectField(env, obj, syncgroupSpecClass.mountTables, x.mountTables.extractToJava(env))
-	C.SetBooleanField(env, obj, syncgroupSpecClass.isPrivate, x.isPrivate.extractToJava())
+func (x *C.v23_syncbase_Strings) extractToJava(env *C.JNIEnv) C.jobject {
+	obj := C.NewObjectA(env, arrayListClass.class, arrayListClass.init, nil)
+	for i := 0; i < int(x.n); i++ {
+		s := x.at(i).extractToJava(env)
+		arg := *(*C.jvalue)(unsafe.Pointer(&s))
+		C.CallBooleanMethodA(env, obj, arrayListClass.add, &arg)
+	}
+	x.free()
 	return obj
 }
 
@@ -554,6 +621,17 @@
 	return obj
 }
 
+func (x *C.v23_syncbase_SyncgroupSpec) extractToJava(env *C.JNIEnv) C.jobject {
+	obj := C.NewObjectA(env, syncgroupSpecClass.class, syncgroupSpecClass.init, nil)
+	C.SetObjectField(env, obj, syncgroupSpecClass.description, x.description.extractToJava(env))
+	C.SetObjectField(env, obj, syncgroupSpecClass.publishSyncbaseName, x.publishSyncbaseName.extractToJava(env))
+	// TODO(razvanm): Also extract the permissions.
+	C.SetObjectField(env, obj, syncgroupSpecClass.collections, x.collections.extractToJava(env))
+	C.SetObjectField(env, obj, syncgroupSpecClass.mountTables, x.mountTables.extractToJava(env))
+	C.SetBooleanField(env, obj, syncgroupSpecClass.isPrivate, x.isPrivate.extractToJava())
+	return obj
+}
+
 func (x *C.v23_syncbase_VError) extractToJava(env *C.JNIEnv) C.jobject {
 	if x.id.p == nil {
 		return nil
@@ -566,14 +644,3 @@
 	x.free()
 	return obj
 }
-
-func (x *C.v23_syncbase_Strings) extractToJava(env *C.JNIEnv) C.jobject {
-	obj := C.NewObjectA(env, arrayListClass.class, arrayListClass.init, nil)
-	for i := 0; i < int(x.n); i++ {
-		s := x.at(i).extractToJava(env)
-		arg := *(*C.jvalue)(unsafe.Pointer(&s))
-		C.CallBooleanMethodA(env, obj, arrayListClass.add, &arg)
-	}
-	x.free()
-	return obj
-}
diff --git a/services/syncbase/bridge/cgo/jni_lib.go b/services/syncbase/bridge/cgo/jni_lib.go
index a83f4c8..8eef51a 100644
--- a/services/syncbase/bridge/cgo/jni_lib.go
+++ b/services/syncbase/bridge/cgo/jni_lib.go
@@ -165,6 +165,38 @@
 	}
 }
 
+type jPermissions struct {
+	class C.jclass
+	init  C.jmethodID
+	json  C.jfieldID
+}
+
+func newJPermissions(env *C.JNIEnv) jPermissions {
+	cls, init := initClass(env, "io/v/syncbase/internal/Permissions")
+	return jPermissions{
+		class: cls,
+		init:  init,
+		json:  jGetFieldID(env, cls, "json", "[B"),
+	}
+}
+
+type jVersionedPermissions struct {
+	class       C.jclass
+	init        C.jmethodID
+	version     C.jfieldID
+	permissions C.jfieldID
+}
+
+func newJVersionedPermissions(env *C.JNIEnv) jVersionedPermissions {
+	cls, init := initClass(env, "io/v/syncbase/internal/VersionedPermissions")
+	return jVersionedPermissions{
+		class:       cls,
+		init:        init,
+		version:     jGetFieldID(env, cls, "version", "Ljava/lang/String;"),
+		permissions: jGetFieldID(env, cls, "permissions", "Lio/v/syncbase/internal/Permissions;"),
+	}
+}
+
 // initClass returns the jclass and the jmethodID of the default constructor for
 // a class.
 func initClass(env *C.JNIEnv, name string) (C.jclass, C.jmethodID) {
diff --git a/services/syncbase/bridge/cgo/jni_types.go b/services/syncbase/bridge/cgo/jni_types.go
index 875833c..d44db28 100644
--- a/services/syncbase/bridge/cgo/jni_types.go
+++ b/services/syncbase/bridge/cgo/jni_types.go
@@ -34,6 +34,9 @@
 
 func newVBytesFromJava(env *C.JNIEnv, array C.jbyteArray) C.v23_syncbase_Bytes {
 	r := C.v23_syncbase_Bytes{}
+	if array == nil {
+		return r
+	}
 	n := C.GetArrayLength(env, array)
 	r.n = C.int(n)
 	r.p = (*C.uint8_t)(C.malloc(C.size_t(r.n)))
@@ -218,9 +221,31 @@
 	if C.ExceptionOccurred(env) != nil {
 		panic("newVSyngroupSpecAndVersionFromJava exception while retrieving VersionedSyncgroupSpec.version")
 	}
-	spec := newVSyngroupSpecFromJava(env, C.GetObjectField(env, obj, versionedSyncgroupSpecClass.syncgroupSpec))
+	cSpec := newVSyngroupSpecFromJava(env, C.GetObjectField(env, obj, versionedSyncgroupSpecClass.syncgroupSpec))
 	if C.ExceptionOccurred(env) != nil {
 		panic("newVSyngroupSpecAndVersionFromJava exception while retrieving VersionedSyncgroupSpec.syncgroupSpec")
 	}
-	return spec, newVStringFromJava(env, version)
+	return cSpec, newVStringFromJava(env, version)
+}
+
+// newVPermissionsFromJava creates a v23_syncbase_Permissions from a Permissions
+// object.
+func newVPermissionsFromJava(env *C.JNIEnv, obj C.jobject) C.v23_syncbase_Permissions {
+	return C.v23_syncbase_Permissions{
+		json: newVBytesFromJava(env, C.jbyteArray(C.GetObjectField(env, obj, permissionsClass.json))),
+	}
+}
+
+// newVPermissionsAndVersionFromJava creates a v23_syncbase_Permissions and
+// v23_syncbase_String version string from a VersionedPermissions object.
+func newVPermissionsAndVersionFromJava(env *C.JNIEnv, obj C.jobject) (C.v23_syncbase_Permissions, C.v23_syncbase_String) {
+	version := C.jstring(C.GetObjectField(env, obj, versionedPermissionsClass.version))
+	if C.ExceptionOccurred(env) != nil {
+		panic("newVPermissionsAndVersionFromJava exception while retrieving VersionedPermissions.version")
+	}
+	cPerms := newVPermissionsFromJava(env, C.GetObjectField(env, obj, versionedPermissionsClass.permissions))
+	if C.ExceptionOccurred(env) != nil {
+		panic("newVPermissionsAndVersionFromJava exception while retrieving VersionedPermissions.permissions")
+	}
+	return cPerms, newVStringFromJava(env, version)
 }