Added PluginServiceHub for use by Corda plugin service extensions.

This commit is contained in:
Jose Coll 2016-10-31 17:15:06 +00:00
parent cd8abffafe
commit 308d7c1df7
6 changed files with 37 additions and 24 deletions

View File

@ -30,8 +30,8 @@ abstract class CordaPluginRegistry {
/**
* List of additional long lived services to be hosted within the node.
* They are expected to have a single parameter constructor that takes a ServiceHubInternal as input.
* The ServiceHubInternal will be fully constructed before the plugin service is created and will
* They are expected to have a single parameter constructor that takes a [PluginServiceHub] as input.
* The [PluginServiceHub] will be fully constructed before the plugin service is created and will
* allow access to the protocol factory and protocol initiation entry points there.
*/
open val servicePlugins: List<Class<*>> = emptyList()

View File

@ -0,0 +1,28 @@
package com.r3corda.core.node
import com.r3corda.core.crypto.Party
import com.r3corda.core.protocols.ProtocolLogic
import kotlin.reflect.KClass
/**
* A service hub to be used by the [CordaPluginRegistry]
*/
interface PluginServiceHub : ServiceHub {
/**
* Register the protocol factory we wish to use when a initiating party attempts to communicate with us. The
* registration is done against a marker [KClass] which is sent in the session handshake by the other party. If this
* marker class has been registered then the corresponding factory will be used to create the protocol which will
* communicate with the other side. If there is no mapping then the session attempt is rejected.
* @param markerClass The marker [KClass] present in a session initiation attempt, which is a 1:1 mapping to a [Class]
* using the <pre>::class</pre> construct. Conventionally this is a [ProtocolLogic] subclass, however any class can
* be used, with the default being the class of the initiating protocol. This enables the registration to be of the
* form: registerProtocolInitiator(InitiatorProtocol::class, ::InitiatedProtocol)
* @param protocolFactory The protocol factory generating the initiated protocol.
*/
fun registerProtocolInitiator(markerClass: KClass<*>, protocolFactory: (Party) -> ProtocolLogic<*>)
/**
* Return the protocol factory that has been registered with [markerClass], or null if no factory is found.
*/
fun getProtocolFactory(markerClass: Class<*>): ((Party) -> ProtocolLogic<*>)?
}

View File

@ -307,7 +307,7 @@ abstract class AbstractNode(open val configuration: NodeConfiguration, val netwo
val pluginServices = pluginRegistries.flatMap { x -> x.servicePlugins }
val serviceList = mutableListOf<Any>()
for (serviceClass in pluginServices) {
val service = serviceClass.getConstructor(ServiceHubInternal::class.java).newInstance(services)
val service = serviceClass.getConstructor(PluginServiceHub::class.java).newInstance(services)
serviceList.add(service)
tokenizableServices.add(service)
if (service is AcceptsFileUpload) {

View File

@ -1,6 +1,7 @@
package com.r3corda.node.services
import com.r3corda.core.node.CordaPluginRegistry
import com.r3corda.core.node.PluginServiceHub
import com.r3corda.core.serialization.SingletonSerializeAsToken
import com.r3corda.node.services.api.ServiceHubInternal
import com.r3corda.protocols.NotaryChangeProtocol
@ -14,7 +15,7 @@ object NotaryChange {
* A service that monitors the network for requests for changing the notary of a state,
* and immediately runs the [NotaryChangeProtocol] if the auto-accept criteria are met.
*/
class Service(services: ServiceHubInternal) : SingletonSerializeAsToken() {
class Service(services: PluginServiceHub) : SingletonSerializeAsToken() {
init {
services.registerProtocolInitiator(NotaryChangeProtocol.Instigator::class) { NotaryChangeProtocol.Acceptor(it) }
}

View File

@ -3,6 +3,7 @@ package com.r3corda.node.services.api
import com.google.common.util.concurrent.ListenableFuture
import com.r3corda.core.crypto.Party
import com.r3corda.core.messaging.MessagingService
import com.r3corda.core.node.PluginServiceHub
import com.r3corda.core.node.ServiceHub
import com.r3corda.core.node.services.TxWritableStorageService
import com.r3corda.core.protocols.ProtocolLogic
@ -37,7 +38,7 @@ interface MessagingServiceBuilder<out T : MessagingServiceInternal> {
private val log = LoggerFactory.getLogger(ServiceHubInternal::class.java)
abstract class ServiceHubInternal : ServiceHub {
abstract class ServiceHubInternal : PluginServiceHub {
abstract val monitoringService: MonitoringService
abstract val protocolLogicRefFactory: ProtocolLogicRefFactory
abstract val schemaService: SchemaService
@ -71,24 +72,6 @@ abstract class ServiceHubInternal : ServiceHub {
*/
abstract fun <T> startProtocol(logic: ProtocolLogic<T>): ListenableFuture<T>
/**
* Register the protocol factory we wish to use when a initiating party attempts to communicate with us. The
* registration is done against a marker [KClass] which is sent in the session handshake by the other party. If this
* marker class has been registered then the corresponding factory will be used to create the protocol which will
* communicate with the other side. If there is no mapping then the session attempt is rejected.
* @param markerClass The marker [KClass] present in a session initiation attempt, which is a 1:1 mapping to a [Class]
* using the <pre>::class</pre> construct. Conventionally this is a [ProtocolLogic] subclass, however any class can
* be used, with the default being the class of the initiating protocol. This enables the registration to be of the
* form: registerProtocolInitiator(InitiatorProtocol::class, ::InitiatedProtocol)
* @param protocolFactory The protocol factory generating the initiated protocol.
*/
abstract fun registerProtocolInitiator(markerClass: KClass<*>, protocolFactory: (Party) -> ProtocolLogic<*>)
/**
* Return the protocol factory that has been registered with [markerClass], or null if no factory is found.
*/
abstract fun getProtocolFactory(markerClass: Class<*>): ((Party) -> ProtocolLogic<*>)?
override fun <T : Any> invokeProtocolAsync(logicType: Class<out ProtocolLogic<T>>, vararg args: Any?): ListenableFuture<T> {
val logicRef = protocolLogicRefFactory.create(logicType, *args)
@Suppress("UNCHECKED_CAST")

View File

@ -3,6 +3,7 @@ package com.r3corda.node.services.persistence
import co.paralleluniverse.fibers.Suspendable
import com.r3corda.core.crypto.Party
import com.r3corda.core.node.CordaPluginRegistry
import com.r3corda.core.node.PluginServiceHub
import com.r3corda.core.node.recordTransactions
import com.r3corda.core.protocols.ProtocolLogic
import com.r3corda.core.serialization.SingletonSerializeAsToken
@ -34,7 +35,7 @@ object DataVending {
// TODO: I don't like that this needs ServiceHubInternal, but passing in a state machine breaks MockServices because
// the state machine isn't set when this is constructed. [NodeSchedulerService] has the same problem, and both
// should be fixed at the same time.
class Service(services: ServiceHubInternal) : SingletonSerializeAsToken() {
class Service(services: PluginServiceHub) : SingletonSerializeAsToken() {
companion object {
val logger = loggerFor<DataVending.Service>()