Пример #1
0
func (i *invoker) Prepare(ctx *context.T, method string, numArgs int) (argptrs []interface{}, tags []*vdl.Value, err error) {
	env, freeFunc := jutil.GetEnv()
	jContext, err := jcontext.JavaContext(env, ctx, nil)
	if err != nil {
		freeFunc()
		return nil, nil, err
	}
	// Have all input arguments be decoded into *vdl.Value.
	argptrs = make([]interface{}, numArgs)
	for i := 0; i < numArgs; i++ {
		value := new(vdl.Value)
		argptrs[i] = &value
	}
	// This method will invoke the freeFunc().
	jVomTags, err := jutil.CallStaticFutureMethod(env, freeFunc, jServerRPCHelperClass, "prepare", []jutil.Sign{invokerSign, contextSign, jutil.StringSign}, i.jInvoker, jContext, jutil.CamelCase(method))
	if err != nil {
		return nil, nil, err
	}
	env, freeFunc = jutil.GetEnv()
	defer freeFunc()
	defer jutil.DeleteGlobalRef(env, jVomTags)
	vomTags, err := jutil.GoByteArrayArray(env, jVomTags)
	if err != nil {
		return nil, nil, err
	}
	tags = make([]*vdl.Value, len(vomTags))
	for i, vomTag := range vomTags {
		var err error
		if tags[i], err = jutil.VomDecodeToValue(vomTag); err != nil {
			return nil, nil, err
		}
	}
	return
}
Пример #2
0
func initDriverFactory(env jutil.Env) error {
	jDriverClass, err := jutil.JFindClass(env, "io/v/android/impl/google/discovery/plugins/ble/Driver")
	if err != nil {
		return err
	}
	factory := func(ctx *context.T, _ string) (ble.Driver, error) {
		env, freeFunc := jutil.GetEnv()
		defer freeFunc()

		jCtx, err := jcontext.JavaContext(env, ctx, nil)
		if err != nil {
			return nil, err
		}
		jDriver, err := jutil.NewObject(env, jDriverClass, []jutil.Sign{contextSign}, jCtx)
		if err != nil {
			return nil, err
		}
		// Reference the driver; it will be de-referenced when the driver is garbage-collected.
		jDriver = jutil.NewGlobalRef(env, jDriver)
		d := &driver{jDriver}
		runtime.SetFinalizer(d, func(*driver) {
			env, freeFunc := jutil.GetEnv()
			jutil.DeleteGlobalRef(env, d.jDriver)
			freeFunc()
		})
		return d, nil
	}
	ble.SetDriverFactory(factory)
	return nil
}
Пример #3
0
func caveatValidator(context *context.T, call security.Call, sets [][]security.Caveat) []error {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jContext, err := jcontext.JavaContext(env, context, nil)
	if err != nil {
		return errors(err, len(sets))
	}
	jCall, err := JavaCall(env, call)
	if err != nil {
		return errors(err, len(sets))
	}
	ret := make([]error, len(sets))
	for i, set := range sets {
		for _, caveat := range set {
			// NOTE(spetrovic): We validate system caveats in Go as it is significantly faster.
			if _, ok := systemCaveats[caveat.Id]; ok {
				if err := caveat.Validate(context, call); err != nil {
					ret[i] = err
					break
				}
			} else {
				jCaveat, err := JavaCaveat(env, caveat)
				if err != nil {
					ret[i] = err
					break
				}
				if err := jutil.CallStaticVoidMethod(env, jCaveatRegistryClass, "validate", []jutil.Sign{contextSign, callSign, caveatSign}, jContext, jCall, jCaveat); err != nil {
					ret[i] = err
					break
				}
			}
		}
	}
	return ret
}
Пример #4
0
func (i *invoker) Signature(ctx *context.T, call rpc.ServerCall) ([]signature.Interface, error) {
	env, freeFunc := jutil.GetEnv()
	jContext, err := jcontext.JavaContext(env, ctx, nil)
	if err != nil {
		freeFunc()
		return nil, err
	}
	// This method will invoke the freeFunc().
	jInterfaces, err := jutil.CallFutureMethod(env, freeFunc, i.jInvoker, "getSignature", []jutil.Sign{contextSign}, jContext)
	if err != nil {
		return nil, err
	}
	env, freeFunc = jutil.GetEnv()
	defer freeFunc()
	defer jutil.DeleteGlobalRef(env, jInterfaces)
	interfacesArr, err := jutil.GoObjectArray(env, jInterfaces)
	if err != nil {
		return nil, err
	}
	result := make([]signature.Interface, len(interfacesArr))
	for i, jInterface := range interfacesArr {
		err = jutil.GoVomCopy(env, jInterface, jInterfaceClass, &result[i])
		if err != nil {
			return nil, err
		}
	}
	return result, nil
}
Пример #5
0
//export Java_io_v_android_v23_V_nativeInitGlobalAndroid
func Java_io_v_android_v23_V_nativeInitGlobalAndroid(jenv *C.JNIEnv, _ C.jclass, jOptions C.jobject) {
	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
	jOpts := jutil.Object(uintptr(unsafe.Pointer(jOptions)))

	// Don't allow broken stderr/out to kill our program due to
	// sigpipe.  Note that we just ignore all these signals.
	ch := make(chan os.Signal)
	signal.Notify(ch, syscall.SIGPIPE)

	if err := Init(env); err != nil {
		jutil.JThrowV(env, err)
		return
	}

	// Setup logging.
	_, _, level, vmodule, err := loggingOpts(env, jOpts)
	if err != nil {
		jutil.JThrowV(env, err)
		return
	}
	// Disable any logging to STDERR.
	// This assumes that vlog.Log is the underlying logging system for.
	vlog.Log.Configure(vlog.OverridePriorConfiguration(true), vlog.LogToStderr(false), vlog.AlsoLogToStderr(false), level, vmodule)

	// Setup discovery plugins.
	if err := jdplugins.Init(env); err != nil {
		jutil.JThrowV(env, err)
		return
	}

	// Setup namespace.
	android.SetNamespaceFactory(func(ctx *context.T, ns namespace.T, _ ...string) (namespace.T, error) {
		env, freeFunc := jutil.GetEnv()
		defer freeFunc()
		jContext, err := jcontext.JavaContext(env, ctx, nil)
		if err != nil {
			return nil, err
		}
		contextSign := jutil.ClassSign("io.v.v23.context.VContext")
		wakeupMountRoot, err := jutil.CallStaticStringMethod(env, jVClass, "getWakeupMountRoot", []jutil.Sign{contextSign}, jContext)
		if err != nil {
			return nil, err
		}
		if wakeupMountRoot == "" {
			return ns, nil
		}
		if !naming.Rooted(wakeupMountRoot) {
			return nil, fmt.Errorf("wakeup mount root %s must be ... rooted.", wakeupMountRoot)
		}
		return &wakeupNamespace{
			wakeupMountRoot: wakeupMountRoot,
			ns:              ns,
		}, nil
	})
}
Пример #6
0
func (btProtocol) Listen(ctx *context.T, protocol, address string) (flow.Listener, error) {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jContext, err := jcontext.JavaContext(env, ctx, nil)
	if err != nil {
		return nil, err
	}
	jListener, err := jutil.CallStaticObjectMethod(env, jBluetoothClass, "listen", []jutil.Sign{contextSign, jutil.StringSign}, listenerSign, jContext, address)
	if err != nil {
		return nil, err
	}
	return newListener(env, jListener), nil
}
Пример #7
0
// JavaInputChannel creates a new Java InputChannel object given the provided Go recv function.
//
// All objects returned by the recv function must be globally references.
//
// The recv function must return verror.ErrEndOfFile when there are no more elements
// to receive.
func JavaInputChannel(env jutil.Env, ctx *context.T, ctxCancel func(), recv func() (jutil.Object, error)) (jutil.Object, error) {
	jContext, err := jcontext.JavaContext(env, ctx, ctxCancel)
	if err != nil {
		return jutil.NullObject, err
	}
	ref := jutil.GoNewRef(&recv) // Un-refed when jInputChannel is finalized.
	jInputChannel, err := jutil.NewObject(env, jInputChannelImplClass, []jutil.Sign{contextSign, jutil.LongSign}, jContext, int64(ref))
	if err != nil {
		jutil.GoDecRef(ref)
		return jutil.NullObject, err
	}
	return jInputChannel, nil
}
Пример #8
0
func (bleProtocol) Dial(ctx *context.T, protocol, address string, timeout time.Duration) (flow.Conn, error) {
	env, freeFunc := jutil.GetEnv()
	jContext, err := jcontext.JavaContext(env, ctx, nil)
	if err != nil {
		freeFunc()
		return nil, err
	}
	// This method will invoke the freeFunc().
	jStream, err := jutil.CallStaticCallbackMethod(env, freeFunc, jBleClass, "dial", []jutil.Sign{contextSign, jutil.StringSign, jutil.DurationSign}, jContext, address, timeout)
	if err != nil {
		return nil, err
	}
	env, freeFunc = jutil.GetEnv()
	defer freeFunc()
	return newConnection(env, jStream), nil
}
Пример #9
0
// JavaOutputChannel creates a new Java OutputChannel object given the provided Go convert, send
// and close functions. Send is invoked with the result of convert, which must be non-blocking.
func JavaOutputChannel(env jutil.Env, ctx *context.T, ctxCancel func(), convert func(jutil.Object) (interface{}, error), send func(interface{}) error, close func() error) (jutil.Object, error) {
	jContext, err := jcontext.JavaContext(env, ctx, ctxCancel)
	if err != nil {
		return jutil.NullObject, err
	}
	convertRef := jutil.GoNewRef(&convert) // Un-refed when jOutputChannel is finalized.
	sendRef := jutil.GoNewRef(&send)       // Un-refed when jOutputChannel is finalized.
	closeRef := jutil.GoNewRef(&close)     // Un-refed when jOutputChannel is finalized.
	jOutputChannel, err := jutil.NewObject(env, jOutputChannelImplClass, []jutil.Sign{contextSign, jutil.LongSign, jutil.LongSign, jutil.LongSign}, jContext, int64(convertRef), int64(sendRef), int64(closeRef))
	if err != nil {
		jutil.GoDecRef(convertRef)
		jutil.GoDecRef(sendRef)
		jutil.GoDecRef(closeRef)
		return jutil.NullObject, err
	}
	return jOutputChannel, nil
}
Пример #10
0
func (a *authorizer) Authorize(ctx *context.T, call security.Call) error {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()

	jCtx, err := jcontext.JavaContext(env, ctx, nil)
	if err != nil {
		return err
	}

	jCall, err := JavaCall(env, call)
	if err != nil {
		return err
	}

	// Run Java Authorizer.
	return jutil.CallVoidMethod(env, a.jAuth, "authorize", []jutil.Sign{contextSign, callSign}, jCtx, jCall)
}
Пример #11
0
func (btProtocol) Dial(ctx *context.T, protocol, address string, timeout time.Duration) (flow.Conn, error) {
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()

	jContext, err := jcontext.JavaContext(env, ctx, nil)
	if err != nil {
		return nil, err
	}
	jStream, err := jutil.CallStaticObjectMethod(env, jBluetoothClass, "dial", []jutil.Sign{contextSign, jutil.StringSign, jutil.DurationSign}, streamSign, jContext, address, timeout)
	if err != nil {
		return nil, err
	}
	// Reference Java Stream; it will be de-referenced when the Go connection
	// created below is garbage-collected (through the finalizer callback we
	// setup just below).
	jStream = jutil.NewGlobalRef(env, jStream)
	return newConnection(env, jStream), nil
}
Пример #12
0
func (j javaGlobber) Glob__(ctx *context.T, call rpc.GlobServerCall, g *glob.Glob) error {
	// TODO(sjr,rthellend): Update the Java API to match the new GO API.
	env, freeFunc := jutil.GetEnv()
	jContext, err := jcontext.JavaContext(env, ctx, nil)
	if err != nil {
		freeFunc()
		return err
	}
	jServerCall, err := JavaServerCall(env, call)
	if err != nil {
		freeFunc()
		return err
	}
	convert := func(input jutil.Object) (interface{}, error) {
		env, freeFunc := jutil.GetEnv()
		defer freeFunc()
		var reply naming.GlobReply
		if err := jutil.GoVomCopy(env, input, jGlobReplyClass, &reply); err != nil {
			return nil, err
		}
		return reply, nil
	}
	send := func(item interface{}) error {
		reply, ok := item.(naming.GlobReply)
		if !ok {
			return fmt.Errorf("Expected item of type naming.GlobReply, got: %T", reply)
		}
		return call.SendStream().Send(reply)
	}
	close := func() error {
		return nil
	}
	jOutputChannel, err := jchannel.JavaOutputChannel(env, ctx, nil, convert, send, close)
	if err != nil {
		freeFunc()
		return err
	}
	channelSign := jutil.ClassSign("io.v.v23.OutputChannel")
	// This method will invoke the freeFunc().
	_, err = jutil.CallStaticFutureMethod(env, freeFunc, jServerRPCHelperClass, "glob", []jutil.Sign{invokerSign, contextSign, serverCallSign, jutil.StringSign, channelSign}, j.i.jInvoker, jContext, jServerCall, g.String(), jOutputChannel)
	return err
}
Пример #13
0
func (i *invoker) Invoke(ctx *context.T, call rpc.StreamServerCall, method string, argptrs []interface{}) (results []interface{}, err error) {
	env, freeFunc := jutil.GetEnv()
	jContext, err := jcontext.JavaContext(env, ctx, nil)
	if err != nil {
		freeFunc()
		return nil, err
	}
	jStreamServerCall, err := javaStreamServerCall(env, jContext, call)
	if err != nil {
		freeFunc()
		return nil, err
	}
	vomArgs := make([][]byte, len(argptrs))
	for i, argptr := range argptrs {
		arg := interface{}(jutil.DerefOrDie(argptr))
		var err error
		if vomArgs[i], err = vom.Encode(arg); err != nil {
			freeFunc()
			return nil, err
		}
	}
	// This method will invoke the freeFunc().
	jResult, err := jutil.CallStaticFutureMethod(env, freeFunc, jServerRPCHelperClass, "invoke", []jutil.Sign{invokerSign, contextSign, streamServerCallSign, jutil.StringSign, jutil.ArraySign(jutil.ArraySign(jutil.ByteSign))}, i.jInvoker, jContext, jStreamServerCall, jutil.CamelCase(method), vomArgs)
	if err != nil {
		return nil, err
	}
	env, freeFunc = jutil.GetEnv()
	defer freeFunc()
	defer jutil.DeleteGlobalRef(env, jResult)
	vomResults, err := jutil.GoByteArrayArray(env, jResult)
	if err != nil {
		return nil, err
	}
	results = make([]interface{}, len(vomResults))
	for i, vomResult := range vomResults {
		var err error
		if results[i], err = jutil.VomDecodeToValue(vomResult); err != nil {
			return nil, err
		}
	}
	return results, nil
}
Пример #14
0
func doStartCall(context *context.T, cancel func(), name, method string, opts []rpc.CallOpt, goRef C.jlong, args []interface{}) (jutil.Object, error) {
	// Invoke StartCall
	call, err := (*(*rpc.Client)(jutil.GoRefValue(jutil.Ref(goRef)))).StartCall(context, name, method, args, opts...)
	if err != nil {
		return jutil.NullObject, err
	}
	env, freeFunc := jutil.GetEnv()
	defer freeFunc()
	jContext, err := jcontext.JavaContext(env, context, cancel)
	if err != nil {
		return jutil.NullObject, err
	}
	jCall, err := javaCall(env, jContext, call)
	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, jCall), nil // Un-refed in DoAsyncCall
}
Пример #15
0
func (i *invoker) MethodSignature(ctx *context.T, call rpc.ServerCall, method string) (signature.Method, error) {
	env, freeFunc := jutil.GetEnv()
	jContext, err := jcontext.JavaContext(env, ctx, nil)
	if err != nil {
		freeFunc()
		return signature.Method{}, err
	}
	// This method will invoke the freeFunc().
	jMethod, err := jutil.CallFutureMethod(env, freeFunc, i.jInvoker, "getMethodSignature", []jutil.Sign{contextSign, jutil.StringSign}, jContext, method)
	if err != nil {
		return signature.Method{}, err
	}
	env, freeFunc = jutil.GetEnv()
	defer freeFunc()
	defer jutil.DeleteGlobalRef(env, jMethod)
	var result signature.Method
	err = jutil.GoVomCopy(env, jMethod, jMethodClass, &result)
	if err != nil {
		return signature.Method{}, err
	}
	return result, nil
}
Пример #16
0
//export Java_io_v_impl_google_services_mounttable_MountTableServer_nativeWithNewServer
func Java_io_v_impl_google_services_mounttable_MountTableServer_nativeWithNewServer(jenv *C.JNIEnv, jMountTableServerClass C.jclass, jContext C.jobject, jMountTableServerParams C.jobject) C.jobject {
	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
	jCtx := jutil.Object(uintptr(unsafe.Pointer(jContext)))
	jParams := jutil.Object(uintptr(unsafe.Pointer(jMountTableServerParams)))

	// Read and translate all of the server params.
	mountName, err := jutil.CallStringMethod(env, jParams, "getName", nil)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	rootDir, err := jutil.CallStringMethod(env, jParams, "getStorageRootDir", nil)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	permsJMap, err := jutil.CallMapMethod(env, jParams, "getPermissions", nil)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	permsMap := make(map[string]access.Permissions)
	for jPath, jPerms := range permsJMap {
		path := jutil.GoString(env, jPath)
		perms, err := jaccess.GoPermissions(env, jPerms)
		if err != nil {
			jutil.JThrowV(env, err)
			return nil
		}
		permsMap[path] = perms
	}
	// Write JSON-encoded permissions to a file.
	jsonPerms, err := json.Marshal(permsMap)
	if err != nil {
		jutil.JThrowV(env, fmt.Errorf("Couldn't JSON-encode path-permissions: %v", err))
		return nil

	}
	permsFile, err := ioutil.TempFile(rootDir, "jni_permissions")
	if err != nil {
		jutil.JThrowV(env, fmt.Errorf("Couldn't create permissions file: %v", err))
		return nil
	}
	w := bufio.NewWriter(permsFile)
	if _, err := w.Write(jsonPerms); err != nil {
		jutil.JThrowV(env, fmt.Errorf("Couldn't write to permissions file: %v", err))
		return nil
	}
	if err := w.Flush(); err != nil {
		jutil.JThrowV(env, fmt.Errorf("Couldn't flush to permissions file: %v", err))
	}
	statsPrefix, err := jutil.CallStringMethod(env, jParams, "getStatsPrefix", nil)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}

	// Start the mounttable server.
	ctx, cancel, err := jcontext.GoContext(env, jCtx)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	d, err := mounttablelib.NewMountTableDispatcher(ctx, permsFile.Name(), rootDir, statsPrefix)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	newCtx, s, err := v23.WithNewDispatchingServer(ctx, mountName, d, options.ServesMountTable(true))
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	jNewCtx, err := jcontext.JavaContext(env, newCtx, cancel)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	jServer, err := jrpc.JavaServer(env, s)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	// Attach a server to the new context.
	jServerAttCtx, err := jutil.CallStaticObjectMethod(env, jVRuntimeImplClass, "withServer", []jutil.Sign{contextSign, serverSign}, contextSign, jNewCtx, jServer)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	return C.jobject(unsafe.Pointer(jServerAttCtx))
}
Пример #17
0
//export Java_io_v_impl_google_services_syncbase_SyncbaseServer_nativeWithNewServer
func Java_io_v_impl_google_services_syncbase_SyncbaseServer_nativeWithNewServer(jenv *C.JNIEnv, jSyncbaseServerClass C.jclass, jContext C.jobject, jSyncbaseServerParams C.jobject) C.jobject {
	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
	jCtx := jutil.Object(uintptr(unsafe.Pointer(jContext)))
	jParams := jutil.Object(uintptr(unsafe.Pointer(jSyncbaseServerParams)))

	// Read and translate all of the server params.
	jPerms, err := jutil.CallObjectMethod(env, jParams, "getPermissions", nil, permissionsSign)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	perms, err := jaccess.GoPermissions(env, jPerms)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	name, err := jutil.CallStringMethod(env, jParams, "getName", nil)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	rootDir, err := jutil.CallStringMethod(env, jParams, "getStorageRootDir", nil)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	if rootDir == "" {
		rootDir = filepath.Join(os.TempDir(), "syncbaseserver")
		if err := os.Mkdir(rootDir, 0755); err != nil && !os.IsExist(err) {
			jutil.JThrowV(env, err)
			return nil
		}
	}
	jEngine, err := jutil.CallObjectMethod(env, jParams, "getStorageEngine", nil, storageEngineSign)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	engine, err := GoStorageEngine(env, jEngine)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	ctx, cancel, err := jcontext.GoContext(env, jCtx)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}

	// Create the rpc server before the service so that connections are shared between
	// clients in the service and the rpc server. (i.e. connections are shared if the
	// context returned from WithNewDispatchingServer is used for client calls).
	d := dispatcher.NewDispatcherWrapper()
	ctx, s, err := v23.WithNewDispatchingServer(ctx, name, d, options.ChannelTimeout(vsync.NeighborConnectionTimeout))
	if err != nil {
		cancel()
		jutil.JThrowV(env, err)
		return nil
	}

	service, err := server.NewService(ctx, server.ServiceOptions{
		Perms:   perms,
		RootDir: rootDir,
		Engine:  engine,
	})
	if err != nil {
		cancel()
		jutil.JThrowV(env, err)
		return nil
	}
	// Set the dispatcher in the dispatcher wrapper for the server to start responding
	// to incoming rpcs.
	d.SetDispatcher(server.NewDispatcher(service))

	if err := service.AddNames(ctx, s); err != nil {
		cancel()
		jutil.JThrowV(env, err)
		return nil
	}
	jNewCtx, err := jcontext.JavaContext(env, ctx, cancel)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	jServer, err := jrpc.JavaServer(env, s)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	// Attach a server to the new context.
	jServerAttCtx, err := jutil.CallStaticObjectMethod(env, jVRuntimeImplClass, "withServer", []jutil.Sign{contextSign, serverSign}, contextSign, jNewCtx, jServer)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	return C.jobject(unsafe.Pointer(jServerAttCtx))
}
Пример #18
0
//export Java_io_v_impl_google_services_groups_GroupServer_nativeWithNewServer
func Java_io_v_impl_google_services_groups_GroupServer_nativeWithNewServer(jenv *C.JNIEnv, jGroupServerClass C.jclass, jContext C.jobject, jGroupServerParams C.jobject) C.jobject {
	env := jutil.Env(uintptr(unsafe.Pointer(jenv)))
	jCtx := jutil.Object(uintptr(unsafe.Pointer(jContext)))
	jParams := jutil.Object(uintptr(unsafe.Pointer(jGroupServerParams)))

	// Read and translate all of the server params.
	name, err := jutil.CallStringMethod(env, jParams, "getName", nil)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	rootDir, err := jutil.CallStringMethod(env, jParams, "getStorageRootDir", nil)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	if rootDir == "" {
		rootDir = filepath.Join(os.TempDir(), "groupserver")
		if err := os.Mkdir(rootDir, 0755); err != nil && !os.IsExist(err) {
			jutil.JThrowV(env, err)
			return nil
		}
	}
	jEngine, err := jutil.CallObjectMethod(env, jParams, "getStorageEngine", nil, storageEngineSign)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	engine, err := GoStorageEngine(env, jEngine)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}

	// Start the server.
	ctx, cancel, err := jcontext.GoContext(env, jCtx)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	dispatcher, err := lib.NewGroupsDispatcher(rootDir, engine)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	newCtx, s, err := v23.WithNewDispatchingServer(ctx, name, dispatcher)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	jNewCtx, err := jcontext.JavaContext(env, newCtx, cancel)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	jServer, err := jrpc.JavaServer(env, s)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	// Attach a server to the new context.
	jServerAttCtx, err := jutil.CallStaticObjectMethod(env, jVRuntimeImplClass, "withServer", []jutil.Sign{contextSign, serverSign}, contextSign, jNewCtx, jServer)
	if err != nil {
		jutil.JThrowV(env, err)
		return nil
	}
	return C.jobject(unsafe.Pointer(jServerAttCtx))
}