hooks.go 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /************************
  2. [钩子引擎 (version 0.3)]
  3. @author:S.W.H
  4. @E-mail:swh@admpub.com
  5. @update:2014-01-18
  6. ************************/
  7. package xweb
  8. import (
  9. "errors"
  10. "fmt"
  11. "reflect"
  12. "sync"
  13. )
  14. var (
  15. ErrParamsNotAdapted = errors.New("The number of params is not adapted.")
  16. XHook *HookEngine = NewHookEngine(10)
  17. )
  18. type Hook []reflect.Value
  19. type HookEngine struct {
  20. Hooks map[string]Hook
  21. Index map[string]uint
  22. lock *sync.RWMutex
  23. }
  24. func (f *HookEngine) Bind(name string, fns ...interface{}) (err error) {
  25. f.lock.Lock()
  26. defer func() {
  27. f.lock.Unlock()
  28. if e := recover(); e != nil {
  29. err = errors.New(name + " is not callable.")
  30. }
  31. }()
  32. if _, ok := f.Hooks[name]; !ok {
  33. f.Hooks[name] = make(Hook, 0)
  34. }
  35. if _, ok := f.Index[name]; !ok {
  36. f.Index[name] = 0
  37. }
  38. hln := uint(len(f.Hooks[name]))
  39. fln := f.Index[name] + 1 + uint(len(fns))
  40. if hln < fln {
  41. for _, fn := range fns {
  42. v := reflect.ValueOf(fn)
  43. f.Hooks[name] = append(f.Hooks[name], v)
  44. f.Index[name]++
  45. }
  46. } else {
  47. for _, fn := range fns {
  48. v := reflect.ValueOf(fn)
  49. f.Hooks[name][f.Index[name]] = v
  50. f.Index[name]++
  51. }
  52. }
  53. return
  54. }
  55. func (f *HookEngine) Call(name string, params ...interface{}) (result []reflect.Value, err error) {
  56. f.lock.Lock()
  57. defer f.lock.Unlock()
  58. if _, ok := f.Hooks[name]; !ok {
  59. err = errors.New(name + " does not exist.")
  60. return
  61. }
  62. ln := len(params)
  63. in := make([]reflect.Value, ln)
  64. for k, param := range params {
  65. in[k] = reflect.ValueOf(param)
  66. }
  67. for _, v := range f.Hooks[name] {
  68. if v.IsValid() == false {
  69. continue
  70. }
  71. if ln != v.Type().NumIn() {
  72. continue
  73. err = ErrParamsNotAdapted
  74. return
  75. }
  76. result = v.Call(in)
  77. for _k, _v := range result {
  78. in[_k] = _v
  79. }
  80. }
  81. if len(result) == 0 {
  82. err = errors.New(name + " have nothing to do.")
  83. }
  84. return
  85. }
  86. func (f *HookEngine) Value(c []reflect.Value, index int) (r interface{}) {
  87. if len(c) >= index && c[index].CanInterface() {
  88. r = c[index].Interface()
  89. }
  90. return
  91. }
  92. func (f *HookEngine) String(c reflect.Value) string {
  93. return fmt.Sprintf("%s", c)
  94. }
  95. func NewHookEngine(size int) *HookEngine {
  96. h := &HookEngine{Hooks: make(map[string]Hook, size), Index: make(map[string]uint, size), lock: new(sync.RWMutex)}
  97. //func(mux *http.ServeMux) *http.ServeMux
  98. h.Hooks["MuxHandle"] = make(Hook, 0)
  99. //func(result *bool, serv *Server, w http.ResponseWriter, req *http.Request) *bool
  100. h.Hooks["BeforeProcess"] = make(Hook, 0)
  101. //func(result *bool, serv *Server, w http.ResponseWriter, req *http.Request) *bool
  102. h.Hooks["AfterProcess"] = make(Hook, 0)
  103. //func(content string, action *Action) string
  104. h.Hooks["BeforeRender"] = make(Hook, 0)
  105. //func(content []byte, action *Action) []byte
  106. h.Hooks["AfterRender"] = make(Hook, 0)
  107. return h
  108. }