forked from cs3org/reva
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathstatic.go
206 lines (178 loc) · 5.25 KB
/
static.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
// Copyright 2018-2021 CERN
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
// In applying this license, CERN does not waive the privileges and immunities
// granted to it by virtue of its status as an Intergovernmental Organization
// or submit itself to any jurisdiction.
package static
import (
"context"
"strings"
"sync"
registrypb "github.com/cs3org/go-cs3apis/cs3/app/registry/v1beta1"
"github.com/cs3org/reva/pkg/app"
"github.com/cs3org/reva/pkg/app/registry/registry"
"github.com/cs3org/reva/pkg/errtypes"
"github.com/cs3org/reva/pkg/sharedconf"
"github.com/mitchellh/mapstructure"
)
func init() {
registry.Register("static", New)
}
type config struct {
Providers map[string]*registrypb.ProviderInfo `mapstructure:"providers"`
}
func (c *config) init() {
if len(c.Providers) == 0 {
c.Providers = map[string]*registrypb.ProviderInfo{
sharedconf.GetGatewaySVC(""): {
Address: sharedconf.GetGatewaySVC(""),
MimeTypes: []string{"text/plain"},
},
}
}
}
func parseConfig(m map[string]interface{}) (*config, error) {
c := &config{}
if err := mapstructure.Decode(m, c); err != nil {
return nil, err
}
return c, nil
}
type mimeTypeIndex struct {
defaultApp string
apps []string
}
type reg struct {
providers map[string]*registrypb.ProviderInfo
mimetypes map[string]*mimeTypeIndex // map the mime type to the addresses of the corresponding providers
sync.RWMutex
}
// New returns an implementation of the app.Registry interface.
func New(m map[string]interface{}) (app.Registry, error) {
c, err := parseConfig(m)
if err != nil {
return nil, err
}
c.init()
newReg := reg{
providers: c.Providers,
mimetypes: make(map[string]*mimeTypeIndex),
}
for addr, p := range c.Providers {
if p != nil {
for _, m := range p.MimeTypes {
_, ok := newReg.mimetypes[m]
if ok {
newReg.mimetypes[m].apps = append(newReg.mimetypes[m].apps, addr)
} else {
newReg.mimetypes[m] = &mimeTypeIndex{apps: []string{addr}}
}
}
}
}
return &newReg, nil
}
func (b *reg) FindProviders(ctx context.Context, mimeType string) ([]*registrypb.ProviderInfo, error) {
// find longest match
var match string
b.RLock()
defer b.RUnlock()
for prefix := range b.mimetypes {
if strings.HasPrefix(mimeType, prefix) && len(prefix) > len(match) {
match = prefix
}
}
if match == "" {
return nil, errtypes.NotFound("application provider not found for mime type " + mimeType)
}
var providers = make([]*registrypb.ProviderInfo, 0, len(b.mimetypes[match].apps))
for _, p := range b.mimetypes[match].apps {
providers = append(providers, b.providers[p])
}
return providers, nil
}
func (b *reg) AddProvider(ctx context.Context, p *registrypb.ProviderInfo) error {
b.Lock()
defer b.Unlock()
b.providers[p.Address] = p
for _, m := range p.MimeTypes {
if _, ok := b.mimetypes[m]; ok {
b.mimetypes[m].apps = append(b.mimetypes[m].apps, p.Address)
} else {
b.mimetypes[m] = &mimeTypeIndex{apps: []string{p.Address}}
}
}
return nil
}
func (b *reg) ListProviders(ctx context.Context) ([]*registrypb.ProviderInfo, error) {
b.RLock()
defer b.RUnlock()
providers := make([]*registrypb.ProviderInfo, 0, len(b.providers))
for _, p := range b.providers {
providers = append(providers, p)
}
return providers, nil
}
func (b *reg) ListSupportedMimeTypes(ctx context.Context) (map[string]*registrypb.AppProviderList, error) {
b.RLock()
defer b.RUnlock()
mimeTypes := make(map[string]*registrypb.AppProviderList)
for _, p := range b.providers {
t := *p
t.MimeTypes = nil
for _, m := range p.MimeTypes {
if _, ok := mimeTypes[m]; ok {
mimeTypes[m].AppProviders = append(mimeTypes[m].AppProviders, &t)
} else {
mimeTypes[m] = ®istrypb.AppProviderList{AppProviders: []*registrypb.ProviderInfo{&t}}
}
}
}
return mimeTypes, nil
}
func (b *reg) SetDefaultProviderForMimeType(ctx context.Context, mimeType string, p *registrypb.ProviderInfo) error {
b.Lock()
defer b.Unlock()
_, ok := b.mimetypes[mimeType]
if ok {
b.mimetypes[mimeType].defaultApp = p.Address
// Add to list of apps if not present
var present bool
for _, pr := range b.mimetypes[mimeType].apps {
if pr == p.Address {
present = true
break
}
}
if !present {
b.mimetypes[mimeType].apps = append(b.mimetypes[mimeType].apps, p.Address)
}
} else {
b.mimetypes[mimeType] = &mimeTypeIndex{apps: []string{p.Address}, defaultApp: p.Address}
}
return nil
}
func (b *reg) GetDefaultProviderForMimeType(ctx context.Context, mimeType string) (*registrypb.ProviderInfo, error) {
b.RLock()
defer b.RUnlock()
_, ok := b.mimetypes[mimeType]
if ok {
p, ok := b.providers[b.mimetypes[mimeType].defaultApp]
if ok {
return p, nil
}
}
return nil, errtypes.NotFound("default application provider not set for mime type " + mimeType)
}