Mercurial > gemma
comparison pkg/geoserver/boot.go @ 876:8b9bd9ccdd93 geo-style
Upload style during boot. TODO: Connect with layer.
author | Sascha L. Teichmann <teichmann@intevation.de> |
---|---|
date | Sun, 30 Sep 2018 19:42:16 +0200 |
parents | 371c756f0370 |
children | 254cd247826d |
comparison
equal
deleted
inserted
replaced
875:371c756f0370 | 876:8b9bd9ccdd93 |
---|---|
1 package geoserver | 1 package geoserver |
2 | 2 |
3 import ( | 3 import ( |
4 "bytes" | 4 "bytes" |
5 "encoding/json" | 5 "encoding/json" |
6 "encoding/xml" | |
6 "fmt" | 7 "fmt" |
8 "io" | |
7 "log" | 9 "log" |
8 "net" | 10 "net" |
9 "net/http" | 11 "net/http" |
10 "net/url" | 12 "net/url" |
11 "strings" | 13 "strings" |
35 | 37 |
36 func asJSON(req *http.Request) { | 38 func asJSON(req *http.Request) { |
37 req.Header.Set("Content-Type", "application/json") | 39 req.Header.Set("Content-Type", "application/json") |
38 } | 40 } |
39 | 41 |
42 func asContentType(req *http.Request, contentType string) { | |
43 req.Header.Set("Content-Type", contentType) | |
44 } | |
45 | |
40 func ensureWorkspace() error { | 46 func ensureWorkspace() error { |
41 var ( | 47 var ( |
42 url = config.GeoServerURL() | 48 geoURL = config.GeoServerURL() |
43 user = config.GeoServerUser() | 49 user = config.GeoServerUser() |
44 password = config.GeoServerPassword() | 50 password = config.GeoServerPassword() |
45 auth = basicAuth(user, password) | 51 auth = basicAuth(user, password) |
46 ) | 52 ) |
47 | 53 |
48 // Probe workspace. | 54 // Probe workspace. |
49 req, err := http.NewRequest( | 55 req, err := http.NewRequest( |
50 http.MethodGet, | 56 http.MethodGet, |
51 url+"/rest/workspaces/"+workspaceName+".json", | 57 geoURL+"/rest/workspaces/"+workspaceName+".json", |
52 nil) | 58 nil) |
53 if err != nil { | 59 if err != nil { |
54 return err | 60 return err |
55 } | 61 } |
56 auth(req) | 62 auth(req) |
70 | 76 |
71 const createJSON = `{"workspace":{"name":"` + workspaceName + `"}}` | 77 const createJSON = `{"workspace":{"name":"` + workspaceName + `"}}` |
72 | 78 |
73 req, err = http.NewRequest( | 79 req, err = http.NewRequest( |
74 http.MethodPost, | 80 http.MethodPost, |
75 url+"/rest/workspaces", | 81 geoURL+"/rest/workspaces", |
76 strings.NewReader(createJSON)) | 82 strings.NewReader(createJSON)) |
77 if err != nil { | 83 if err != nil { |
78 return err | 84 return err |
79 } | 85 } |
80 auth(req) | 86 auth(req) |
92 return err | 98 return err |
93 } | 99 } |
94 | 100 |
95 func ensureDataStore() error { | 101 func ensureDataStore() error { |
96 var ( | 102 var ( |
97 url = config.GeoServerURL() | 103 geoURL = config.GeoServerURL() |
98 user = config.GeoServerUser() | 104 user = config.GeoServerUser() |
99 password = config.GeoServerPassword() | 105 password = config.GeoServerPassword() |
100 auth = basicAuth(user, password) | 106 auth = basicAuth(user, password) |
101 ) | 107 ) |
102 | 108 |
103 // Probe datastore. | 109 // Probe datastore. |
104 req, err := http.NewRequest( | 110 req, err := http.NewRequest( |
105 http.MethodGet, | 111 http.MethodGet, |
106 url+"/rest/workspaces/"+workspaceName+"/datastores/"+datastoreName+".json", | 112 geoURL+"/rest/workspaces/"+workspaceName+"/datastores/"+datastoreName+".json", |
107 nil) | 113 nil) |
108 if err != nil { | 114 if err != nil { |
109 return err | 115 return err |
110 } | 116 } |
111 auth(req) | 117 auth(req) |
152 return err | 158 return err |
153 } | 159 } |
154 | 160 |
155 req, err = http.NewRequest( | 161 req, err = http.NewRequest( |
156 http.MethodPost, | 162 http.MethodPost, |
157 url+"/rest/workspaces/"+workspaceName+"/datastores", | 163 geoURL+"/rest/workspaces/"+workspaceName+"/datastores", |
158 bytes.NewReader(out.Bytes())) | 164 bytes.NewReader(out.Bytes())) |
159 if err != nil { | 165 if err != nil { |
160 return err | 166 return err |
161 } | 167 } |
162 auth(req) | 168 auth(req) |
175 return err | 181 return err |
176 } | 182 } |
177 | 183 |
178 func ensureFeatures() error { | 184 func ensureFeatures() error { |
179 var ( | 185 var ( |
180 url = config.GeoServerURL() | 186 geoURL = config.GeoServerURL() |
181 user = config.GeoServerUser() | 187 user = config.GeoServerUser() |
182 password = config.GeoServerPassword() | 188 password = config.GeoServerPassword() |
183 auth = basicAuth(user, password) | 189 auth = basicAuth(user, password) |
184 ) | 190 ) |
185 | 191 |
209 } | 215 } |
210 | 216 |
211 // Fetch all featuretypes. | 217 // Fetch all featuretypes. |
212 req, err := http.NewRequest( | 218 req, err := http.NewRequest( |
213 http.MethodGet, | 219 http.MethodGet, |
214 url+"/rest/workspaces/"+workspaceName+ | 220 geoURL+"/rest/workspaces/"+workspaceName+ |
215 "/datastores/"+datastoreName+ | 221 "/datastores/"+datastoreName+ |
216 "/featuretypes.json", | 222 "/featuretypes.json", |
217 nil) | 223 nil) |
218 if err != nil { | 224 if err != nil { |
219 return err | 225 return err |
261 return err | 267 return err |
262 } | 268 } |
263 | 269 |
264 req, err := http.NewRequest( | 270 req, err := http.NewRequest( |
265 http.MethodPost, | 271 http.MethodPost, |
266 url+"/rest/workspaces/"+workspaceName+ | 272 geoURL+"/rest/workspaces/"+workspaceName+ |
267 "/datastores/"+datastoreName+ | 273 "/datastores/"+datastoreName+ |
268 "/featuretypes", | 274 "/featuretypes", |
269 bytes.NewReader(out.Bytes())) | 275 bytes.NewReader(out.Bytes())) |
270 if err != nil { | 276 if err != nil { |
271 return err | 277 return err |
294 return nil | 300 return nil |
295 } | 301 } |
296 | 302 |
297 log.Println("info: delete workspace " + workspaceName) | 303 log.Println("info: delete workspace " + workspaceName) |
298 var ( | 304 var ( |
299 url = config.GeoServerURL() | 305 geoURL = config.GeoServerURL() |
300 user = config.GeoServerUser() | 306 user = config.GeoServerUser() |
301 password = config.GeoServerPassword() | 307 password = config.GeoServerPassword() |
302 auth = basicAuth(user, password) | 308 auth = basicAuth(user, password) |
303 ) | 309 ) |
304 | 310 |
305 req, err := http.NewRequest( | 311 req, err := http.NewRequest( |
306 http.MethodDelete, | 312 http.MethodDelete, |
307 url+"/rest/workspaces/"+workspaceName+"?recurse=true", | 313 geoURL+"/rest/workspaces/"+workspaceName+"?recurse=true", |
308 nil) | 314 nil) |
309 if err != nil { | 315 if err != nil { |
310 return err | 316 return err |
311 } | 317 } |
312 auth(req) | 318 auth(req) |
315 } | 321 } |
316 | 322 |
317 func ensureStyles() error { | 323 func ensureStyles() error { |
318 log.Println("info: creating styles") | 324 log.Println("info: creating styles") |
319 | 325 |
320 // TODO: Implement me! | 326 var ( |
327 geoURL = config.GeoServerURL() | |
328 user = config.GeoServerUser() | |
329 password = config.GeoServerPassword() | |
330 auth = basicAuth(user, password) | |
331 ) | |
332 | |
333 type styles struct { | |
334 Styles struct { | |
335 Style []struct { | |
336 Name string `json:"name"` | |
337 } `json:"style"` | |
338 } `json:"styles"` | |
339 } | |
340 | |
341 var stls styles | |
342 | |
343 hasStyle := func(name string) bool { | |
344 for i := range stls.Styles.Style { | |
345 if stls.Styles.Style[i].Name == name { | |
346 return true | |
347 } | |
348 } | |
349 return false | |
350 } | |
351 | |
352 req, err := http.NewRequest( | |
353 http.MethodGet, | |
354 geoURL+"/rest/workspaces/"+workspaceName+"/styles.json", | |
355 nil) | |
356 if err != nil { | |
357 return err | |
358 } | |
359 auth(req) | |
360 resp, err := http.DefaultClient.Do(req) | |
361 if err != nil { | |
362 return err | |
363 } | |
364 | |
365 // Fetch all styles | |
366 if err := json.NewDecoder(resp.Body).Decode(&stls); err != nil { | |
367 // XXX: Same quirk as with featuretypes. | |
368 } | |
369 resp.Body.Close() | |
370 | |
371 entries := models.InternalServices.Filter( | |
372 models.IntAnd(models.IntWMS, models.IntWithStyle)) | |
373 | |
374 for i := range entries { | |
375 if hasStyle(entries[i].Name) { | |
376 log.Printf("already has style for %s\n", entries[i].Name) | |
377 continue | |
378 } | |
379 | |
380 log.Printf("creating style %s\n", entries[i].Name) | |
381 | |
382 req, err := http.NewRequest( | |
383 http.MethodPost, | |
384 geoURL+"/rest/workspaces/"+workspaceName+"/styles?name="+ | |
385 url.QueryEscape(entries[i].Name), | |
386 strings.NewReader(entries[i].Style.String)) | |
387 if err != nil { | |
388 return err | |
389 } | |
390 auth(req) | |
391 if isSymbologyEncoding(entries[i].Style.String) { | |
392 asContentType(req, "application/vnd.ogc.se+xml") | |
393 } else { | |
394 asContentType(req, "application/vnd.ogc.sld+xml") | |
395 } | |
396 resp, err := http.DefaultClient.Do(req) | |
397 if err != nil { | |
398 return err | |
399 } | |
400 | |
401 if resp.StatusCode != http.StatusCreated { | |
402 return fmt.Errorf("cannot create style %s (%s)", | |
403 entries[i].Name, http.StatusText(resp.StatusCode)) | |
404 } | |
405 | |
406 // TODO: Connect with feature. | |
407 } | |
321 | 408 |
322 return nil | 409 return nil |
410 } | |
411 | |
412 // isSymbologyEncoding tries to figure out if its plain SLD or SE. | |
413 func isSymbologyEncoding(data string) bool { | |
414 decoder := xml.NewDecoder(strings.NewReader(data)) | |
415 for { | |
416 tok, err := decoder.Token() | |
417 switch { | |
418 case tok == nil && err == io.EOF: | |
419 return false | |
420 case err != nil: | |
421 log.Printf("warn: invalid XML: %v\n", err) | |
422 return false | |
423 } | |
424 if t, ok := tok.(xml.StartElement); ok && | |
425 t.Name.Space == "http://www.opengis.net/se" { | |
426 return true | |
427 } | |
428 } | |
323 } | 429 } |
324 | 430 |
325 func prepareGeoServer() error { | 431 func prepareGeoServer() error { |
326 | 432 |
327 if config.DBUser() == "" { | 433 if config.DBUser() == "" { |