Capstan is a Golang web framework that shares some similarities with others in its segment.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
3.0KB

  1. package capstan
  2. import (
  3. "net/http"
  4. "sync"
  5. )
  6. // TODO: Extensions should be included in the server configuration so they can
  7. // be initialized with the consideration of their dependencies. At the moment,
  8. // they're initialized as they're loaded.
  9. type Extension interface {
  10. // Name for this extension; symbolic.
  11. Name() string
  12. // Provides indicates the dependency fulfilled by this extension.
  13. Provides() string
  14. // Requires indicates which dependency or dependencies must be loaded prior
  15. // to this extension.
  16. Requires() []string
  17. // Init this extension. This is called after the extension has been loaded;
  18. // for extensions that have dependencies on other extensions, this is called
  19. // after the dependency has been loaded. Circular dependencies will result
  20. // in a panic.
  21. Init(app Application)
  22. }
  23. type ExtensionDeinitializer interface {
  24. // Deinit this extension. This is called before Capstan finalizes all
  25. // connections and shuts down. Extensions that implement this interface will
  26. // be given an opportunity to perform teardowns required.
  27. Deinit(app Application)
  28. }
  29. type MiddlewareExtension interface {
  30. Extension
  31. // Middleware should return any middleware required by this extension.
  32. Middleware() []func(http.Handler) http.Handler
  33. }
  34. type DependencyMapperExtension interface {
  35. Extension
  36. // Dependency name and value for automatically binding this extension into
  37. // the dependency mapper. Most extensions will prefer doing this manually
  38. // via calling the dependency mapper directly after SetServer passes in the
  39. // active Capstan.Server instance, but implementing this interface allows
  40. // the Capstan extension manager to perform the function automatically. The
  41. // returned interface may be the extension itself or it may be any other
  42. // value/structure used by the extension.
  43. //
  44. // Bear in mind that whatever value is exported via this method must also be
  45. // importable from the defined controllers that rely on the dependency.
  46. Dependency() (string, interface{})
  47. }
  48. type ExtensionManager struct {
  49. extensions map[string]Extension
  50. provides map[string]Extension
  51. depends map[string][]Extension
  52. app Application
  53. sync.RWMutex
  54. }
  55. func NewExtensionManager(app Application) *ExtensionManager {
  56. return &ExtensionManager{
  57. extensions: make(map[string]Extension),
  58. provides: make(map[string]Extension),
  59. depends: make(map[string][]Extension),
  60. app: app,
  61. }
  62. }
  63. func (m *ExtensionManager) Init() *ExtensionManager {
  64. for _, ext := range m.extensions {
  65. ext.Init(m.app)
  66. }
  67. return m
  68. }
  69. func (m *ExtensionManager) Register(extension Extension) error {
  70. m.Lock()
  71. m.extensions[extension.Name()] = extension
  72. /*m.provides[extension.Provides()] = extension
  73. failed := make([]string, 0)
  74. if len(extension.Requires()) > 0 {
  75. for _, requirement := range extension.Requires() {
  76. if _, ok := m.provides[requirement]; !ok {
  77. failed = append(failed, requirement)
  78. }
  79. }
  80. }
  81. if len(failed) > 0 {
  82. return errors.New("failed dependencies: requires (missing): " +
  83. strings.Join(failed, ", "))
  84. }*/
  85. m.Unlock()
  86. extension.Init(m.app)
  87. return nil
  88. }