github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/handlers/library/registry.go (about)

     1  /*
     2  Copyright hechain, SecureKey Technologies Inc. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package library
     8  
     9  import (
    10  	"fmt"
    11  	"reflect"
    12  	"sync"
    13  
    14  	"github.com/hechain20/hechain/common/flogging"
    15  	"github.com/hechain20/hechain/core/handlers/auth"
    16  	"github.com/hechain20/hechain/core/handlers/decoration"
    17  	endorsement2 "github.com/hechain20/hechain/core/handlers/endorsement/api"
    18  	validation "github.com/hechain20/hechain/core/handlers/validation/api"
    19  )
    20  
    21  var logger = flogging.MustGetLogger("core.handlers")
    22  
    23  // Registry defines an object that looks up
    24  // handlers by name
    25  type Registry interface {
    26  	// Lookup returns a handler with a given
    27  	// registered name, or nil if does not exist
    28  	Lookup(HandlerType) interface{}
    29  }
    30  
    31  // HandlerType defines custom handlers that can filter and mutate
    32  // objects passing within the peer
    33  type HandlerType int
    34  
    35  const (
    36  	// Auth handler - reject or forward proposals from clients
    37  	Auth HandlerType = iota
    38  	// Decoration handler - append or mutate the chaincode input
    39  	// passed to the chaincode
    40  	Decoration
    41  	Endorsement
    42  	Validation
    43  
    44  	authPluginFactory      = "NewFilter"
    45  	decoratorPluginFactory = "NewDecorator"
    46  	pluginFactory          = "NewPluginFactory"
    47  )
    48  
    49  type registry struct {
    50  	filters    []auth.Filter
    51  	decorators []decoration.Decorator
    52  	endorsers  map[string]endorsement2.PluginFactory
    53  	validators map[string]validation.PluginFactory
    54  }
    55  
    56  var (
    57  	once sync.Once
    58  	reg  registry
    59  )
    60  
    61  // InitRegistry creates the (only) instance
    62  // of the registry
    63  func InitRegistry(c Config) Registry {
    64  	once.Do(func() {
    65  		reg = registry{
    66  			endorsers:  make(map[string]endorsement2.PluginFactory),
    67  			validators: make(map[string]validation.PluginFactory),
    68  		}
    69  		reg.loadHandlers(c)
    70  	})
    71  	return &reg
    72  }
    73  
    74  // loadHandlers loads the configured handlers
    75  func (r *registry) loadHandlers(c Config) {
    76  	for _, config := range c.AuthFilters {
    77  		r.evaluateModeAndLoad(config, Auth)
    78  	}
    79  	for _, config := range c.Decorators {
    80  		r.evaluateModeAndLoad(config, Decoration)
    81  	}
    82  
    83  	for chaincodeID, config := range c.Endorsers {
    84  		r.evaluateModeAndLoad(config, Endorsement, chaincodeID)
    85  	}
    86  
    87  	for chaincodeID, config := range c.Validators {
    88  		r.evaluateModeAndLoad(config, Validation, chaincodeID)
    89  	}
    90  }
    91  
    92  // evaluateModeAndLoad if a library path is provided, load the shared object
    93  func (r *registry) evaluateModeAndLoad(c *HandlerConfig, handlerType HandlerType, extraArgs ...string) {
    94  	if c.Library != "" {
    95  		r.loadPlugin(c.Library, handlerType, extraArgs...)
    96  	} else {
    97  		r.loadCompiled(c.Name, handlerType, extraArgs...)
    98  	}
    99  }
   100  
   101  // loadCompiled loads a statically compiled handler
   102  func (r *registry) loadCompiled(handlerFactory string, handlerType HandlerType, extraArgs ...string) {
   103  	registryMD := reflect.ValueOf(&HandlerLibrary{})
   104  
   105  	o := registryMD.MethodByName(handlerFactory)
   106  	if !o.IsValid() {
   107  		logger.Panicf(fmt.Sprintf("Method %s isn't a method of HandlerLibrary", handlerFactory))
   108  	}
   109  
   110  	inst := o.Call(nil)[0].Interface()
   111  
   112  	if handlerType == Auth {
   113  		r.filters = append(r.filters, inst.(auth.Filter))
   114  	} else if handlerType == Decoration {
   115  		r.decorators = append(r.decorators, inst.(decoration.Decorator))
   116  	} else if handlerType == Endorsement {
   117  		if len(extraArgs) != 1 {
   118  			logger.Panicf("expected 1 argument in extraArgs")
   119  		}
   120  		r.endorsers[extraArgs[0]] = inst.(endorsement2.PluginFactory)
   121  	} else if handlerType == Validation {
   122  		if len(extraArgs) != 1 {
   123  			logger.Panicf("expected 1 argument in extraArgs")
   124  		}
   125  		r.validators[extraArgs[0]] = inst.(validation.PluginFactory)
   126  	}
   127  }
   128  
   129  // Lookup returns a list of handlers with the given
   130  // type, or nil if none exist
   131  func (r *registry) Lookup(handlerType HandlerType) interface{} {
   132  	if handlerType == Auth {
   133  		return r.filters
   134  	} else if handlerType == Decoration {
   135  		return r.decorators
   136  	} else if handlerType == Endorsement {
   137  		return r.endorsers
   138  	} else if handlerType == Validation {
   139  		return r.validators
   140  	}
   141  
   142  	return nil
   143  }