github.com/kaituanwang/hyperledger@v2.0.1+incompatible/core/handlers/library/registry.go (about) 1 /* 2 Copyright IBM Corp, 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 "os" 12 "plugin" 13 "reflect" 14 "sync" 15 16 "github.com/hyperledger/fabric/common/flogging" 17 "github.com/hyperledger/fabric/core/handlers/auth" 18 "github.com/hyperledger/fabric/core/handlers/decoration" 19 endorsement2 "github.com/hyperledger/fabric/core/handlers/endorsement/api" 20 validation "github.com/hyperledger/fabric/core/handlers/validation/api" 21 ) 22 23 var logger = flogging.MustGetLogger("core.handlers") 24 25 // Registry defines an object that looks up 26 // handlers by name 27 type Registry interface { 28 // Lookup returns a handler with a given 29 // registered name, or nil if does not exist 30 Lookup(HandlerType) interface{} 31 } 32 33 // HandlerType defines custom handlers that can filter and mutate 34 // objects passing within the peer 35 type HandlerType int 36 37 const ( 38 // Auth handler - reject or forward proposals from clients 39 Auth HandlerType = iota 40 // Decoration handler - append or mutate the chaincode input 41 // passed to the chaincode 42 Decoration 43 Endorsement 44 Validation 45 46 authPluginFactory = "NewFilter" 47 decoratorPluginFactory = "NewDecorator" 48 pluginFactory = "NewPluginFactory" 49 ) 50 51 type registry struct { 52 filters []auth.Filter 53 decorators []decoration.Decorator 54 endorsers map[string]endorsement2.PluginFactory 55 validators map[string]validation.PluginFactory 56 } 57 58 var once sync.Once 59 var reg registry 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 ® 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 // loadPlugin loads a pluggable handler 130 func (r *registry) loadPlugin(pluginPath string, handlerType HandlerType, extraArgs ...string) { 131 if _, err := os.Stat(pluginPath); err != nil { 132 logger.Panicf(fmt.Sprintf("Could not find plugin at path %s: %s", pluginPath, err)) 133 } 134 p, err := plugin.Open(pluginPath) 135 if err != nil { 136 logger.Panicf(fmt.Sprintf("Error opening plugin at path %s: %s", pluginPath, err)) 137 } 138 139 if handlerType == Auth { 140 r.initAuthPlugin(p) 141 } else if handlerType == Decoration { 142 r.initDecoratorPlugin(p) 143 } else if handlerType == Endorsement { 144 r.initEndorsementPlugin(p, extraArgs...) 145 } else if handlerType == Validation { 146 r.initValidationPlugin(p, extraArgs...) 147 } 148 } 149 150 // initAuthPlugin constructs an auth filter from the given plugin 151 func (r *registry) initAuthPlugin(p *plugin.Plugin) { 152 constructorSymbol, err := p.Lookup(authPluginFactory) 153 if err != nil { 154 panicWithLookupError(authPluginFactory, err) 155 } 156 constructor, ok := constructorSymbol.(func() auth.Filter) 157 if !ok { 158 panicWithDefinitionError(authPluginFactory) 159 } 160 161 filter := constructor() 162 if filter != nil { 163 r.filters = append(r.filters, filter) 164 } 165 } 166 167 // initDecoratorPlugin constructs a decorator from the given plugin 168 func (r *registry) initDecoratorPlugin(p *plugin.Plugin) { 169 constructorSymbol, err := p.Lookup(decoratorPluginFactory) 170 if err != nil { 171 panicWithLookupError(decoratorPluginFactory, err) 172 } 173 constructor, ok := constructorSymbol.(func() decoration.Decorator) 174 if !ok { 175 panicWithDefinitionError(decoratorPluginFactory) 176 } 177 decorator := constructor() 178 if decorator != nil { 179 r.decorators = append(r.decorators, constructor()) 180 } 181 } 182 183 func (r *registry) initEndorsementPlugin(p *plugin.Plugin, extraArgs ...string) { 184 if len(extraArgs) != 1 { 185 logger.Panicf("expected 1 argument in extraArgs") 186 } 187 factorySymbol, err := p.Lookup(pluginFactory) 188 if err != nil { 189 panicWithLookupError(pluginFactory, err) 190 } 191 192 constructor, ok := factorySymbol.(func() endorsement2.PluginFactory) 193 if !ok { 194 panicWithDefinitionError(pluginFactory) 195 } 196 factory := constructor() 197 if factory == nil { 198 logger.Panicf("factory instance returned nil") 199 } 200 r.endorsers[extraArgs[0]] = factory 201 } 202 203 func (r *registry) initValidationPlugin(p *plugin.Plugin, extraArgs ...string) { 204 if len(extraArgs) != 1 { 205 logger.Panicf("expected 1 argument in extraArgs") 206 } 207 factorySymbol, err := p.Lookup(pluginFactory) 208 if err != nil { 209 panicWithLookupError(pluginFactory, err) 210 } 211 212 constructor, ok := factorySymbol.(func() validation.PluginFactory) 213 if !ok { 214 panicWithDefinitionError(pluginFactory) 215 } 216 factory := constructor() 217 if factory == nil { 218 logger.Panicf("factory instance returned nil") 219 } 220 r.validators[extraArgs[0]] = factory 221 } 222 223 // panicWithLookupError panics when a handler constructor lookup fails 224 func panicWithLookupError(factory string, err error) { 225 logger.Panicf(fmt.Sprintf("Plugin must contain constructor with name %s. Error from lookup: %s", 226 factory, err)) 227 } 228 229 // panicWithDefinitionError panics when a handler constructor does not match 230 // the expected function definition 231 func panicWithDefinitionError(factory string) { 232 logger.Panicf(fmt.Sprintf("Constructor method %s does not match expected definition", 233 factory)) 234 } 235 236 // Lookup returns a list of handlers with the given 237 // type, or nil if none exist 238 func (r *registry) Lookup(handlerType HandlerType) interface{} { 239 if handlerType == Auth { 240 return r.filters 241 } else if handlerType == Decoration { 242 return r.decorators 243 } else if handlerType == Endorsement { 244 return r.endorsers 245 } else if handlerType == Validation { 246 return r.validators 247 } 248 249 return nil 250 }