blob: 35b542ecf27f51a830cb517223a4b92612d84f9e [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// +build java android
package namespace
import (
"time"
"unsafe"
"v.io/v23/context"
"v.io/v23/namespace"
"v.io/v23/naming"
"v.io/v23/security/access"
"v.io/v23/verror"
jchannel "v.io/x/jni/impl/google/channel"
jutil "v.io/x/jni/util"
jcontext "v.io/x/jni/v23/context"
)
// #include "jni.h"
import "C"
var (
// Global reference for io.v.impl.google.namespace.NamespaceImpl class.
jNamespaceImplClass jutil.Class
// Global reference for io.v.v23.naming.GlobReply class.
jGlobReplyClass jutil.Class
// Global reference for io.v.v23.naming.MountEntry class.
JMountEntryClass jutil.Class
// Global reference for io.v.v23.security.access.Permissions
jPermissionsClass jutil.Class
)
// Init initializes the JNI code with the given Java environment. This method
// must be called from the main Java thread.
func Init(env jutil.Env) error {
var err error
jNamespaceImplClass, err = jutil.JFindClass(env, "io/v/impl/google/namespace/NamespaceImpl")
if err != nil {
return err
}
jGlobReplyClass, err = jutil.JFindClass(env, "io/v/v23/naming/GlobReply")
if err != nil {
return err
}
JMountEntryClass, err = jutil.JFindClass(env, "io/v/v23/naming/MountEntry")
if err != nil {
return err
}
jPermissionsClass, err = jutil.JFindClass(env, "io/v/v23/security/access/Permissions")
if err != nil {
return err
}
return nil
}
func globArgs(env jutil.Env, jContext C.jobject, jPattern C.jstring, jOptions C.jobject) (context *context.T, cancel func(), pattern string, opts []naming.NamespaceOpt, err error) {
context, cancel, err = jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
if err != nil {
return
}
opts, err = goNamespaceOptions(env, jutil.Object(uintptr(unsafe.Pointer(jOptions))))
if err != nil {
return
}
pattern = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jPattern))))
return
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeGlob
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeGlob(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jContext C.jobject, jPattern C.jstring, jOptions C.jobject) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
ctx, cancel, pattern, opts, err := globArgs(env, jContext, jPattern, jOptions)
if err != nil {
jutil.JThrowV(env, err)
return nil
}
var globChannel <-chan naming.GlobReply
var globError error
globDone := make(chan bool)
go func() {
globChannel, globError = n.Glob(ctx, pattern, opts...)
close(globDone)
}()
jChannel, err := jchannel.JavaInputChannel(env, ctx, cancel, func() (jutil.Object, error) {
// A few blocking calls below - don't call GetEnv() before they complete.
<-globDone
if globError != nil {
return jutil.NullObject, globError
}
globReply, ok := <-globChannel
if !ok {
return jutil.NullObject, verror.NewErrEndOfFile(ctx)
}
env, freeFunc := jutil.GetEnv()
defer freeFunc()
jReply, err := jutil.JVomCopy(env, globReply, jGlobReplyClass)
if err != nil {
return jutil.NullObject, err
}
// Must grab a global reference as we free up the env and all local references that come
// along with it.
return jutil.NewGlobalRef(env, jReply), nil // Un-refed by InputChannelImpl_nativeRecv
})
if err != nil {
jutil.JThrowV(env, err)
return nil
}
return C.jobject(unsafe.Pointer(jChannel))
}
func mountArgs(env jutil.Env, jContext C.jobject, jName, jServer C.jstring, jDuration, jOptions C.jobject) (context *context.T, name, server string, duration time.Duration, options []naming.NamespaceOpt, err error) {
context, _, err = jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
if err != nil {
return
}
name = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
server = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jServer))))
duration, err = jutil.GoDuration(env, jutil.Object(uintptr(unsafe.Pointer(jDuration))))
if err != nil {
return
}
options, err = goNamespaceOptions(env, jutil.Object(uintptr(unsafe.Pointer(jOptions))))
return
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeMount
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeMount(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jContext C.jobject, jName C.jstring, jServer C.jstring, jDuration C.jobject, jOptions C.jobject, jCallbackObj C.jobject) {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
jCallback := jutil.Object(uintptr(unsafe.Pointer(jCallbackObj)))
context, name, server, duration, options, err := mountArgs(env, jContext, jName, jServer, jDuration, jOptions)
if err != nil {
jutil.CallbackOnFailure(env, jCallback, err)
return
}
jutil.DoAsyncCall(env, jCallback, func() (jutil.Object, error) {
return jutil.NullObject, n.Mount(context, name, server, duration, options...)
})
}
func unmountArgs(env jutil.Env, jName, jServer C.jstring, jContext, jOptions C.jobject) (name, server string, context *context.T, options []naming.NamespaceOpt, err error) {
name = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
server = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jServer))))
context, _, err = jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
if err != nil {
return
}
options, err = goNamespaceOptions(env, jutil.Object(uintptr(unsafe.Pointer(jOptions))))
return
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeUnmount
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeUnmount(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jContext C.jobject, jName C.jstring, jServer C.jstring, jOptions C.jobject, jCallbackObj C.jobject) {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
jCallback := jutil.Object(uintptr(unsafe.Pointer(jCallbackObj)))
name, server, context, options, err := unmountArgs(env, jName, jServer, jContext, jOptions)
if err != nil {
jutil.CallbackOnFailure(env, jCallback, err)
return
}
jutil.DoAsyncCall(env, jCallback, func() (jutil.Object, error) {
return jutil.NullObject, n.Unmount(context, name, server, options...)
})
}
func deleteArgs(env jutil.Env, jContext, jOptions C.jobject, jName C.jstring, jDeleteSubtree C.jboolean) (context *context.T, options []naming.NamespaceOpt, name string, deleteSubtree bool, err error) {
context, _, err = jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
if err != nil {
return
}
options, err = goNamespaceOptions(env, jutil.Object(uintptr(unsafe.Pointer(jOptions))))
if err != nil {
return
}
name = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
deleteSubtree = jDeleteSubtree == C.JNI_TRUE
return
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeDelete
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeDelete(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jContext C.jobject, jName C.jstring, jDeleteSubtree C.jboolean, jOptions C.jobject, jCallbackObj C.jobject) {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
jCallback := jutil.Object(uintptr(unsafe.Pointer(jCallbackObj)))
context, options, name, deleteSubtree, err := deleteArgs(env, jContext, jOptions, jName, jDeleteSubtree)
if err != nil {
jutil.CallbackOnFailure(env, jCallback, err)
return
}
jutil.DoAsyncCall(env, jCallback, func() (jutil.Object, error) {
return jutil.NullObject, n.Delete(context, name, deleteSubtree, options...)
})
}
func resolveArgs(env jutil.Env, jName C.jstring, jContext, jOptions C.jobject) (context *context.T, name string, options []naming.NamespaceOpt, err error) {
context, _, err = jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
if err != nil {
return
}
options, err = goNamespaceOptions(env, jutil.Object(uintptr(unsafe.Pointer(jOptions))))
if err != nil {
return
}
name = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
return
}
func doResolve(n namespace.T, context *context.T, name string, options []naming.NamespaceOpt) (jutil.Object, error) {
entry, err := n.Resolve(context, name, options...)
if err != nil {
return jutil.NullObject, err
}
env, freeFunc := jutil.GetEnv()
defer freeFunc()
jEntry, err := jutil.JVomCopy(env, entry, JMountEntryClass)
if err != nil {
return jutil.NullObject, err
}
// Must grab a global reference as we free up the env and all local references that come along
// with it.
return jutil.NewGlobalRef(env, jEntry), nil // Un-refed in DoAsyncCall
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeResolve
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeResolve(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jContext C.jobject, jName C.jstring, jOptions C.jobject, jCallbackObj C.jobject) {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
jCallback := jutil.Object(uintptr(unsafe.Pointer(jCallbackObj)))
context, name, options, err := resolveArgs(env, jName, jContext, jOptions)
if err != nil {
jutil.CallbackOnFailure(env, jCallback, err)
return
}
jutil.DoAsyncCall(env, jCallback, func() (jutil.Object, error) {
return doResolve(n, context, name, options)
})
}
func resolveToMountTableArgs(env jutil.Env, jContext, jOptions C.jobject, jName C.jstring) (context *context.T, options []naming.NamespaceOpt, name string, err error) {
context, _, err = jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
if err != nil {
return
}
options, err = goNamespaceOptions(env, jutil.Object(uintptr(unsafe.Pointer(jOptions))))
if err != nil {
return
}
name = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
return
}
func doResolveToMountTable(n namespace.T, context *context.T, name string, options []naming.NamespaceOpt) (jutil.Object, error) {
entry, err := n.ResolveToMountTable(context, name, options...)
if err != nil {
return jutil.NullObject, err
}
env, freeFunc := jutil.GetEnv()
defer freeFunc()
jEntry, err := jutil.JVomCopy(env, entry, JMountEntryClass)
if err != nil {
return jutil.NullObject, err
}
// Must grab a global reference as we free up the env and all local references that come along
// with it.
return jutil.NewGlobalRef(env, jEntry), nil // Un-refed in DoAsyncCall
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeResolveToMountTable
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeResolveToMountTable(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jContext C.jobject, jName C.jstring, jOptions C.jobject, jCallbackObj C.jobject) {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
jCallback := jutil.Object(uintptr(unsafe.Pointer(jCallbackObj)))
context, options, name, err := resolveToMountTableArgs(env, jContext, jOptions, jName)
if err != nil {
jutil.CallbackOnFailure(env, jCallback, err)
return
}
jutil.DoAsyncCall(env, jCallback, func() (jutil.Object, error) {
return doResolveToMountTable(n, context, name, options)
})
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeSetCachingPolicy
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeSetCachingPolicy(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jDoCaching C.jboolean) C.jboolean {
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
disable := naming.DisableCache(false)
if jDoCaching == C.JNI_FALSE {
disable = naming.DisableCache(true)
}
oldCtls := n.CacheCtl(disable)
var oldDisable naming.DisableCache
for _, ctl := range oldCtls {
switch value := ctl.(type) {
case naming.DisableCache:
oldDisable = value
}
}
if oldDisable {
return C.JNI_FALSE
}
return C.JNI_TRUE
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeFlushCacheEntry
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeFlushCacheEntry(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jContext C.jobject, jName C.jstring) C.jboolean {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
context, _, err := jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
if err != nil {
jutil.JThrowV(env, err)
return C.JNI_FALSE
}
result := n.FlushCacheEntry(context, jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName)))))
if result {
return C.JNI_TRUE
} else {
return C.JNI_FALSE
}
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeSetRoots
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeSetRoots(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jNames C.jobject) {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
names, err := jutil.GoStringList(env, jutil.Object(uintptr(unsafe.Pointer(jNames))))
if err != nil {
jutil.JThrowV(env, err)
return
}
err = n.SetRoots(names...)
if err != nil {
jutil.JThrowV(env, err)
}
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeGetRoots
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeGetRoots(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong) C.jobject {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
roots := n.Roots()
jRoots, err := jutil.JStringList(env, roots)
if err != nil {
jutil.JThrowV(env, err)
return nil
}
return C.jobject(unsafe.Pointer(jRoots))
}
func setPermissionsArgs(env jutil.Env, jContext, jPermissions C.jobject, jName, jVersion C.jstring, jOptions C.jobject) (context *context.T, permissions access.Permissions, name, version string, options []naming.NamespaceOpt, err error) {
context, _, err = jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
if err != nil {
return
}
err = jutil.GoVomCopy(env, jutil.Object(uintptr(unsafe.Pointer(jPermissions))), jPermissionsClass, &permissions)
if err != nil {
return
}
options, err = goNamespaceOptions(env, jutil.Object(uintptr(unsafe.Pointer(jOptions))))
name = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
version = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jVersion))))
return
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeSetPermissions
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeSetPermissions(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jContext C.jobject, jName C.jstring, jPermissions C.jobject, jVersion C.jstring, jOptions C.jobject, jCallbackObj C.jobject) {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
jCallback := jutil.Object(uintptr(unsafe.Pointer(jCallbackObj)))
context, permissions, name, version, options, err := setPermissionsArgs(env, jContext, jPermissions, jName, jVersion, jOptions)
if err != nil {
jutil.CallbackOnFailure(env, jCallback, err)
return
}
jutil.DoAsyncCall(env, jCallback, func() (jutil.Object, error) {
return jutil.NullObject, n.SetPermissions(context, name, permissions, version, options...)
})
}
func getPermissionsArgs(env jutil.Env, jContext C.jobject, jName C.jstring, jOptions C.jobject) (context *context.T, name string, options []naming.NamespaceOpt, err error) {
context, _, err = jcontext.GoContext(env, jutil.Object(uintptr(unsafe.Pointer(jContext))))
if err != nil {
return
}
options, err = goNamespaceOptions(env, jutil.Object(uintptr(unsafe.Pointer(jOptions))))
if err != nil {
return
}
name = jutil.GoString(env, jutil.Object(uintptr(unsafe.Pointer(jName))))
return
}
func doGetPermissions(n namespace.T, context *context.T, name string, options []naming.NamespaceOpt) (jutil.Object, error) {
permissions, version, err := n.GetPermissions(context, name, options...)
if err != nil {
return jutil.NullObject, err
}
env, freeFunc := jutil.GetEnv()
defer freeFunc()
jPermissions, err := jutil.JVomCopy(env, permissions, jPermissionsClass)
if err != nil {
return jutil.NullObject, err
}
result := make(map[jutil.Object]jutil.Object)
result[jutil.JString(env, version)] = jPermissions
jResult, err := jutil.JObjectMap(env, result)
if err != nil {
return jutil.NullObject, err
}
// Must grab a global reference as we free up the env and all local references that come along
// with it.
return jutil.NewGlobalRef(env, jResult), nil // Un-refed in DoAsyncCall
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeGetPermissions
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeGetPermissions(jenv *C.JNIEnv, jNamespaceClass C.jclass, goRef C.jlong, jContext C.jobject, jName C.jstring, jOptions C.jobject, jCallbackObj C.jobject) {
env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
n := *(*namespace.T)(jutil.GoRefValue(jutil.Ref(goRef)))
jCallback := jutil.Object(uintptr(unsafe.Pointer(jCallbackObj)))
context, name, options, err := getPermissionsArgs(env, jContext, jName, jOptions)
if err != nil {
jutil.CallbackOnFailure(env, jCallback, err)
return
}
jutil.DoAsyncCall(env, jCallback, func() (jutil.Object, error) {
return doGetPermissions(n, context, name, options)
})
}
//export Java_io_v_impl_google_namespace_NamespaceImpl_nativeFinalize
func Java_io_v_impl_google_namespace_NamespaceImpl_nativeFinalize(jenv *C.JNIEnv, jNamespace C.jobject, goRef C.jlong) {
jutil.GoDecRef(jutil.Ref(goRef))
}