add support for BlessingRoots.Dump()
Change-Id: Iafe72f09a1f121608a011fef918eac959bc77739
diff --git a/util/call.go b/util/call.go
index c9c73f2..faa63f0 100644
--- a/util/call.go
+++ b/util/call.go
@@ -315,6 +315,47 @@
return ret, nil
}
+// CallMultimapMethod calls a Java method that returns a Multimap.
+func CallMultimapMethod(env interface{}, object interface{}, name string, argSigns []Sign, args ...interface{}) (map[unsafe.Pointer][]unsafe.Pointer, error) {
+ jMultimap, err := CallObjectMethod(env, object, name, argSigns, MultimapSign, args...)
+ if err != nil {
+ return nil, err
+ }
+ if jMultimap == nil {
+ return nil, nil
+ }
+ jEntrySet, err := CallObjectMethod(env, jMultimap, "entrySet", nil, SetSign)
+ if err != nil {
+ return nil, err
+ }
+ jIter, err := CallObjectMethod(env, jEntrySet, "iterator", nil, IteratorSign)
+ if err != nil {
+ return nil, err
+ }
+ ret := make(map[unsafe.Pointer][]unsafe.Pointer)
+ for {
+ if hasNext, err := CallBooleanMethod(env, jIter, "hasNext", nil); err != nil {
+ return nil, err
+ } else if !hasNext {
+ break
+ }
+ jEntry, err := CallObjectMethod(env, jIter, "next", nil, ObjectSign)
+ if err != nil {
+ return nil, err
+ }
+ jKey, err := CallObjectMethod(env, jEntry, "getKey", nil, ObjectSign)
+ if err != nil {
+ return nil, err
+ }
+ jValue, err := CallObjectMethod(env, jEntry, "getValue", nil, ObjectSign)
+ if err != nil {
+ return nil, err
+ }
+ ret[jKey] = append(ret[jKey], jValue)
+ }
+ return ret, nil
+}
+
// CallBooleanMethod calls a Java method that returns a boolean.
func CallBooleanMethod(env interface{}, object interface{}, name string, argSigns []Sign, args ...interface{}) (bool, error) {
jenv, jobject, jmid, valArray, freeFunc, err := setupMethodCall(env, object, name, argSigns, BoolSign, args)
diff --git a/util/sign.go b/util/sign.go
index 58171c2..2256559 100644
--- a/util/sign.go
+++ b/util/sign.go
@@ -43,6 +43,8 @@
SetSign = ClassSign("java.util.Set")
// MapSign denotes a signature of a Java Map type.
MapSign = ClassSign("java.util.Map")
+ // MultimapSign denotes a signature of a Guava Multimap type.
+ MultimapSign = ClassSign("com.google.common.collect.Multimap")
// IteratorSign denotes a signature of a Java Iterator type.
IteratorSign = ClassSign("java.util.Iterator")
// ByteArraySign denotes a signature of a Java byte array type.
diff --git a/util/util.go b/util/util.go
index ff137f6..0c313d7 100644
--- a/util/util.go
+++ b/util/util.go
@@ -53,6 +53,8 @@
jStringClass C.jclass
// Global reference for java.util.HashMap class.
jHashMapClass C.jclass
+ // Global reference for com.google.common.collect.HashMultimap class.
+ jHashMultimapClass C.jclass
// Global reference for []byte class.
jByteArrayClass C.jclass
// Cached Java VM.
@@ -127,6 +129,11 @@
return err
}
jHashMapClass = C.jclass(class)
+ class, err = JFindClass(env, "com/google/common/collect/HashMultimap")
+ if err != nil {
+ return err
+ }
+ jHashMultimapClass = C.jclass(class)
class, err = JFindClass(env, "[B")
if err != nil {
return err
@@ -642,6 +649,27 @@
return unsafe.Pointer(jMap), nil
}
+// JObjectMultimap converts the provided Go map of Java objects into a Java
+// object multimap.
+// NOTE: Because CGO creates package-local types and because this method may be
+// invoked from a different package, Java types are passed in an empty interface
+// and then cast into their package local types.
+func JObjectMultimap(jEnv interface{}, goMap map[interface{}][]interface{}) (unsafe.Pointer, error) {
+ env := getEnv(jEnv)
+ jMap, err := NewObject(env, jHashMultimapClass, nil)
+ if err != nil {
+ return nil, err
+ }
+ for jKey, jVals := range goMap {
+ for _, jVal := range jVals {
+ if _, err := CallBooleanMethod(env, jMap, "put", []Sign{ObjectSign, ObjectSign}, getObject(jKey), getObject(jVal)); err != nil {
+ return nil, err
+ }
+ }
+ }
+ return unsafe.Pointer(jMap), nil
+}
+
// GoObjectMap converts the provided Java object map into a Go map of Java
// objects.
// NOTE: Because CGO creates package-local types and because this method may be
diff --git a/v23/security/jni.go b/v23/security/jni.go
index d243b2b..31c5138 100644
--- a/v23/security/jni.go
+++ b/v23/security/jni.go
@@ -605,6 +605,34 @@
return C.jstring(jutil.JString(env, str))
}
+//export Java_io_v_v23_security_BlessingRootsImpl_nativeDump
+func Java_io_v_v23_security_BlessingRootsImpl_nativeDump(env *C.JNIEnv, jBlessingStoreImpl C.jobject, goPtr C.jlong) C.jobject {
+ dump := (*(*security.BlessingRoots)(jutil.Ptr(goPtr))).Dump()
+ result := make(map[interface{}][]interface{})
+ for pattern, keys := range dump {
+ jBlessingPattern, err := JavaBlessingPattern(env, pattern)
+ if err != nil {
+ jutil.JThrowV(env, err)
+ return nil
+ }
+ jPublicKeys := make([]interface{}, len(keys))
+ for i, key := range keys {
+ var err error
+ if jPublicKeys[i], err = JavaPublicKey(env, key); err != nil {
+ jutil.JThrowV(env, err)
+ return nil
+ }
+ }
+ result[jBlessingPattern] = jPublicKeys
+ }
+ jMap, err := jutil.JObjectMultimap(env, result)
+ if err != nil {
+ jutil.JThrowV(env, err)
+ return nil
+ }
+ return C.jobject(jMap)
+}
+
//export Java_io_v_v23_security_BlessingRootsImpl_nativeFinalize
func Java_io_v_v23_security_BlessingRootsImpl_nativeFinalize(env *C.JNIEnv, jBlessingRootsImpl C.jobject, goPtr C.jlong) {
jutil.GoUnref(jutil.Ptr(goPtr))
diff --git a/v23/security/roots.go b/v23/security/roots.go
index 533eafa..8f33278 100644
--- a/v23/security/roots.go
+++ b/v23/security/roots.go
@@ -95,3 +95,32 @@
}
return ret
}
+
+func (r *blessingRoots) Dump() map[security.BlessingPattern][]security.PublicKey {
+ env, freeFunc := jutil.GetEnv()
+ defer freeFunc()
+ ret, err := jutil.CallMultimapMethod(env, r.jBlessingRoots, "dump", []jutil.Sign{})
+ if err != nil {
+ log.Printf("Couldn't get Java Dump: %v", err)
+ return nil
+ }
+ result := make(map[security.BlessingPattern][]security.PublicKey)
+ for jPattern, jKeys := range ret {
+ pattern, err := GoBlessingPattern(env, jPattern)
+ if err != nil {
+ log.Printf("Couldn't convert Java BlessingPattern: %v", err)
+ return nil
+ }
+ var entry []security.PublicKey
+ for _, jKey := range jKeys {
+ key, err := GoPublicKey(env, jKey)
+ if err != nil {
+ log.Printf("Couldn't convert Java PublicKey: %v", err)
+ return nil
+ }
+ entry = append(entry, key)
+ }
+ result[pattern] = entry
+ }
+ return result
+}