| // 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 security |
| |
| import ( |
| "log" |
| "runtime" |
| "time" |
| |
| jutil "v.io/x/jni/util" |
| jcontext "v.io/x/jni/v23/context" |
| |
| "v.io/v23" |
| "v.io/v23/context" |
| "v.io/v23/naming" |
| "v.io/v23/security" |
| "v.io/v23/vdl" |
| ) |
| |
| // #include "jni.h" |
| import "C" |
| |
| // JavaCall converts the provided Go (security) Call into a Java Call object. |
| func JavaCall(env jutil.Env, call security.Call) (jutil.Object, error) { |
| ref := jutil.GoNewRef(&call) // Un-refed when the Java CallImpl object is finalized. |
| jCall, err := jutil.NewObject(env, jCallImplClass, []jutil.Sign{jutil.LongSign}, int64(ref)) |
| if err != nil { |
| jutil.GoDecRef(ref) |
| return jutil.NullObject, err |
| } |
| return jCall, nil |
| } |
| |
| // GoCall creates instance of security.Call that uses the provided Java |
| // Call as its underlying implementation. |
| func GoCall(env jutil.Env, jCall jutil.Object) (security.Call, error) { |
| if jCall.IsNull() { |
| return nil, nil |
| } |
| if jutil.IsInstanceOf(env, jCall, jCallImplClass) { |
| // Called with our implementation of Call, which maintains a Go reference - use it. |
| ref, err := jutil.CallLongMethod(env, jCall, "nativeRef", nil) |
| if err != nil { |
| return nil, err |
| } |
| return (*(*security.Call)(jutil.GoRefValue(jutil.Ref(ref)))), nil |
| } |
| // Reference Java call; it will be de-referenced when the go call |
| // created below is garbage-collected (through the finalizer callback we |
| // setup just below). |
| jCall = jutil.NewGlobalRef(env, jCall) |
| call := &callImpl{ |
| jCall: jCall, |
| } |
| runtime.SetFinalizer(call, func(c *callImpl) { |
| env, freeFunc := jutil.GetEnv() |
| defer freeFunc() |
| jutil.DeleteGlobalRef(env, c.jCall) |
| }) |
| return call, nil |
| } |
| |
| // callImpl is the go interface to the java implementation of security.Call |
| type callImpl struct { |
| jCall jutil.Object |
| } |
| |
| func (c *callImpl) Timestamp() time.Time { |
| env, freeFunc := jutil.GetEnv() |
| defer freeFunc() |
| jTime, err := jutil.CallObjectMethod(env, c.jCall, "timestamp", nil, jutil.DateTimeSign) |
| if err != nil { |
| log.Println("Couldn't call Java timestamp method: ", err) |
| return time.Time{} |
| } |
| t, err := jutil.GoTime(env, jTime) |
| if err != nil { |
| log.Println("Couldn't convert Java time to Go: ", err) |
| return time.Time{} |
| } |
| return t |
| } |
| |
| func (c *callImpl) Method() string { |
| return jutil.UpperCamelCase(c.callStringMethod("method")) |
| } |
| |
| func (c *callImpl) MethodTags() []*vdl.Value { |
| env, freeFunc := jutil.GetEnv() |
| defer freeFunc() |
| jTags, err := jutil.CallObjectMethod(env, c.jCall, "methodTags", nil, jutil.ArraySign(jutil.VdlValueSign)) |
| if err != nil { |
| log.Println("Couldn't call Java methodTags method: ", err) |
| return nil |
| } |
| tags, err := jutil.GoVDLValueArray(env, jTags) |
| if err != nil { |
| log.Println("Couldn't convert Java tags to Go: ", err) |
| return nil |
| } |
| return tags |
| } |
| |
| func (c *callImpl) Suffix() string { |
| return c.callStringMethod("suffix") |
| } |
| |
| func (c *callImpl) LocalDischarges() map[string]security.Discharge { |
| return c.callDischargeMapMethod("localDischarges") |
| } |
| |
| func (c *callImpl) RemoteDischarges() map[string]security.Discharge { |
| return c.callDischargeMapMethod("remoteDischarges") |
| } |
| |
| func (c *callImpl) LocalEndpoint() naming.Endpoint { |
| epStr := c.callStringMethod("localEndpoint") |
| ep, err := v23.NewEndpoint(epStr) |
| if err != nil { |
| log.Printf("Couldn't parse endpoint string %q: %v", epStr, err) |
| return nil |
| } |
| return ep |
| } |
| |
| func (c *callImpl) LocalPrincipal() security.Principal { |
| env, freeFunc := jutil.GetEnv() |
| defer freeFunc() |
| jPrincipal, err := jutil.CallObjectMethod(env, c.jCall, "localPrincipal", nil, principalSign) |
| if err != nil { |
| log.Printf("Couldn't call Java localPrincipal method: %v", err) |
| return nil |
| } |
| principal, err := GoPrincipal(env, jPrincipal) |
| if err != nil { |
| log.Printf("Couldn't convert Java principal to Go: %v", err) |
| return nil |
| } |
| return principal |
| } |
| |
| func (c *callImpl) LocalBlessings() security.Blessings { |
| env, freeFunc := jutil.GetEnv() |
| defer freeFunc() |
| jBlessings, err := jutil.CallObjectMethod(env, c.jCall, "localBlessings", nil, blessingsSign) |
| if err != nil { |
| log.Printf("Couldn't call Java localBlessings method: %v", err) |
| return security.Blessings{} |
| } |
| blessings, err := GoBlessings(env, jBlessings) |
| if err != nil { |
| log.Printf("Couldn't convert Java Blessings into Go: %v", err) |
| return security.Blessings{} |
| } |
| return blessings |
| } |
| |
| func (c *callImpl) RemoteBlessings() security.Blessings { |
| env, freeFunc := jutil.GetEnv() |
| defer freeFunc() |
| jBlessings, err := jutil.CallObjectMethod(env, c.jCall, "remoteBlessings", nil, blessingsSign) |
| if err != nil { |
| log.Printf("Couldn't call Java remoteBlessings method: %v", err) |
| return security.Blessings{} |
| } |
| blessings, err := GoBlessings(env, jBlessings) |
| if err != nil { |
| log.Printf("Couldn't convert Java Blessings into Go: %v", err) |
| return security.Blessings{} |
| } |
| return blessings |
| } |
| |
| func (c *callImpl) RemoteEndpoint() naming.Endpoint { |
| epStr := c.callStringMethod("remoteEndpoint") |
| ep, err := v23.NewEndpoint(epStr) |
| if err != nil { |
| log.Printf("Couldn't parse endpoint string %q: %v", epStr, err) |
| return nil |
| } |
| return ep |
| } |
| |
| func (c *callImpl) Context() *context.T { |
| env, freeFunc := jutil.GetEnv() |
| defer freeFunc() |
| contextSign := jutil.ClassSign("io.v.v23.context.VContext") |
| jCtx, err := jutil.CallObjectMethod(env, c.jCall, "context", nil, contextSign) |
| if err != nil { |
| log.Printf("Couldn't get Java Vanadium context: %v", err) |
| } |
| ctx, _, err := jcontext.GoContext(env, jCtx) |
| if err != nil { |
| log.Printf("Couldn't convert Java Vanadium context to Go: %v", err) |
| } |
| return ctx |
| } |
| |
| func (c *callImpl) callStringMethod(methodName string) string { |
| env, freeFunc := jutil.GetEnv() |
| defer freeFunc() |
| ret, err := jutil.CallStringMethod(env, c.jCall, methodName, nil) |
| if err != nil { |
| log.Printf("Couldn't call Java %q method: %v", methodName, err) |
| return "" |
| } |
| return ret |
| } |
| |
| func (c *callImpl) callDischargeMapMethod(methodName string) map[string]security.Discharge { |
| env, freeFunc := jutil.GetEnv() |
| defer freeFunc() |
| javaObjectMap, err := jutil.CallMapMethod(env, c.jCall, methodName, nil) |
| if err != nil { |
| log.Printf("Couldn't call Java %q method: %v", methodName, err) |
| return nil |
| } |
| discharges := make(map[string]security.Discharge) |
| for jKey, jValue := range javaObjectMap { |
| key := jutil.GoString(env, jKey) |
| discharge, err := GoDischarge(env, jValue) |
| if err != nil { |
| log.Printf("Couldn't convert Java Discharge to Go Discharge: %v", err) |
| return nil |
| } |
| discharges[key] = discharge |
| } |
| return discharges |
| } |